Skip to main content

Kibo Shipment Packages API Developer Guide

Understanding Shipment Packages in Kibo

In Kibo, it’s essential to distinguish between a Shipment and a Package. A Shipment is an abstract concept representing a group of items from an order that are being fulfilled together. A Package, the focus of this guide, is the tangible, physical box that you put those items into. You can have a single shipment that is split across multiple packages, each with its own dimensions, weight, and tracking number. What makes Kibo’s approach different is that creating a Package is a distinct, explicit step in the fulfillment workflow. It’s the point where the abstract “shipment” becomes a real-world object ready for a shipping label. This explicit step allows for granular control over the packing process and precise communication with shipping carriers.

How This Domain Fits Into Kibo

The Shipment Packages domain is a key part of the Fulfillment process and is tightly coupled with the Order domain. It represents the final stage of preparing an order for dispatch.
  • Fulfillment & Shipments: A Package is always a child of a Shipment. You cannot create a package without first having a shipment to associate it with. The shipment dictates what items need to be packed, and the package records how they are packed.
  • Orders: Creating packages and generating shipping labels are key steps that trigger order status updates. Once a package has a shipping label, the associated shipment is typically marked as “Fulfilled,” and the customer is notified with the tracking information.
  • Carrier Integration: The details you provide when creating a package (like weight and dimensions) are sent directly to integrated shipping carriers (like FedEx or UPS) to generate accurate shipping labels and rates.

Prerequisites

  • Kibo API credentials and basic setup
  • Node.js 16+ with TypeScript
  • Familiarity with REST APIs

What You’ll Learn

After completing this guide, you’ll understand:
  • How Kibo models physical packages as distinct objects within a shipment (based on official API specs).
  • The key patterns for creating, updating, and deleting packages as part of the fulfillment process (verified from apidocs.kibocommerce.com).
  • The common workflow for packing items and preparing a shipment for label generation.
  • How to avoid the most common beginner mistakes, like trying to create a package for a shipment that isn’t ready.
  • How to read and navigate the official Shipments API documentation effectively.

Kibo Shipment Packages Fundamentals

How Kibo Organizes Package Data

The data model is hierarchical and straightforward:
  • Order: Contains one or more Shipments.
  • Shipment: A group of items to be fulfilled. It is identified by a shipmentNumber. A shipment must be in the “Ready” state before you can create packages for it.
  • Package: The core object of this guide. It is a child of a Shipment and is identified by a system-generated packageId. Its key properties include:
    • packagingType: A string indicating the type of box (e.g., “Custom” or a carrier-specific type like “FedEx_Box”).
    • measurements: An object containing the weight and length, width, height.
    • items: An array specifying which items from the parent shipment (and in what quantity) are in this specific box.

Key Kibo Patterns You’ll See Everywhere

Before we write code, understand these patterns that appear in every Kibo API: Authentication Pattern: The Kibo SDK manages authentication for you. You create a single Configuration object containing your credentials (Client ID, Shared Secret, etc.). This object is then passed to the constructor of specific API clients (e.g., new ShipmentApi(configuration)). Request/Response Structure: When you create a new package, the API returns the complete Package object, including its newly assigned packageId.
// Actual response schema for POST /commerce/shipments/{shipmentNumber}/packages
{
  "packageId": "a1b2c3d4e5f6",
  "packagingType": "Custom",
  "measurements": {
    "weight": { "value": 5, "unit": "lbs" },
    "length": { "value": 12, "unit": "in" },
    "width": { "value": 10, "unit": "in" },
    "height": { "value": 8, "unit": "in" }
  },
  "items": [
    {
      "productCode": "SHIRT-BLUE-M",
      "quantity": 1
    }
  ]
}
Error Handling Approach: If an API call fails, the SDK throws a structured error. A common error in this domain is a VALIDATION_ERROR if you try to create a package for a shipment that is not yet in a “Ready” state.
// Actual error schema from Kibo
{
    "message": "The shipment is not in a valid state to create a package. Current status is 'Pending'.",
    "errorCode": "VALIDATION_ERROR",
    "correlationId": "e0b5b9b0-a5f1-4f1e-9a0c-12345abcdef"
}
API Documentation Reference: All package operations are part of the Shipments API group. Find complete specs at: /developer-guides/shipments

Common Shipment Package Workflows

  1. Standard Fulfillment: A warehouse worker scans the items for a shipment, puts them in a box, weighs it, and a system calls the API to create the package record before generating a shipping label.
  2. Multi-Package Shipment: An order for one large item and one small item is fulfilled in two separate boxes. Two Package objects are created under the same Shipment, each containing the appropriate item and its own dimensions.
  3. Correcting Mistakes: A worker realizes they used the wrong box size. A system calls the API to update the package with the correct dimensions before the shipping label is created.
Let’s explore each CRUD operation step by step.

New Shipment Package: The Kibo Way

When You Need This

This is the core operation in the packing process. You need this after you have physically placed items into a box and are ready to record its contents, weight, and dimensions in Kibo. This is the prerequisite for generating a shipping label.

API Documentation Reference

Endpoint: POST /commerce/shipments/{shipmentNumber}/packages Method: POST API Docs: /developer-guides/shipments#new-shipment-package

Understanding the Kibo Approach

Kibo requires you to be explicit about what is in each box. The API call to create a package requires you to specify which items from the parent shipment are included. This creates a detailed digital packing slip for each physical package, which is useful for accurate tracking, customer service, and managing claims with carriers if a package is lost or damaged.

Code Structure Walkthrough

// We'll build this step by step:
// 1. **Configuration**: Create a central Configuration instance.
// 2. **API Client Instantiation**: Create a client for the Shipments API.
// 3. **Data Preparation**: Construct the request body for the new Package, detailing its contents and measurements.
// 4. **API Call**: Use the instantiated client to call the `newShipmentPackage` method.

Step-by-Step Implementation

Step 1: Setting Up the Foundation
// Essential imports for Shipment Package operations.
import { Configuration } from "@kibocommerce/rest-sdk";
import { ShipmentPackagesApi } from "@kibocommerce/rest-sdk/clients/Fulfillment";
import { Package } from "@kibocommerce/rest-sdk/models/Fulfillment";

const configuration = new Configuration({
    tenantId: process.env.KIBO_TENANT_ID,
    siteId: process.env.KIBO_SITE_ID,
    clientId: process.env.KIBO_CLIENT_ID,
    sharedSecret: process.env.KIBO_SHARED_SECRET,
    authHost: process.env.KIBO_AUTH_HOST,
});
Step 2: The Core Implementation
// Complete working example that ACTUALLY WORKS with the Kibo API
// This function creates a new package for a given shipment.

async function createNewPackage(
    shipmentNumber: number,
    packageDetails: Package
): Promise<Package> {
    console.log(`Creating a new package for shipment ${shipmentNumber}...`);

    // 1. Instantiate a dedicated client for the Shipment Packages API.
    const shipmentPackagesApi = new ShipmentPackagesApi(configuration);

    // 2. The packageDetails object is our request payload.
    // It must match the schema defined in the Kibo API documentation.

    // 3. Call the method on the client.
    try {
        const newPackage = await shipmentPackagesApi.newPackage({
            shipmentNumber,
            packageDto: packageDetails,
        });
        console.log(`Success! Package with ID "${newPackage.packageId}" created.`);
        return newPackage;
    } catch (error) {
        console.error("API Error creating package:", JSON.stringify(error, null, 2));
        throw error;
    }
}

// Example usage:
// Assume shipment #10052 has one item: { productCode: 'TSHIRT-BLK-L', quantity: 2 }
// We are packing both items into one box.
// const newPackagePayload: ModelPackage = {
//     packagingType: "Custom",
//     measurements: {
//         weight: { value: 2.5, unit: "lbs" },
//         length: { value: 12, unit: "in" },
//         width: { value: 12, unit: "in" },
//         height: { value: 4, unit: "in" }
//     },
//     items: [
//         {
//             productCode: "TSHIRT-BLK-L",
//             quantity: 2
//         }
//     ]
// };
// createNewPackage(10052, newPackagePayload);

What Just Happened? (Code Explanation)

  • The setup phase created the standard Configuration object.
  • We used an instance of ShipmentApi, as all package operations are nested under shipments.
  • The payload we prepared was a ModelPackage object that precisely described the physical box: its dimensions, weight, and the exact contents from the parent shipment.
  • The newShipmentPackage call sent this data to Kibo. Kibo validated that the items were part of the shipment and that the shipment was in a “Ready” state, then created the package record and returned it with its new packageId.

Update & Delete Shipment Packages

Update Shipment Package

When You Need This: If you need to correct the weight, dimensions, or contents of a package before a shipping label has been generated. For example, a packer uses a different box than originally planned, or a scale gives a more accurate weight. API Documentation Reference:
// This function updates an existing package. Note: PUT is a full replacement.
async function updatePackageDetails(
    shipmentNumber: number,
    packageId: string,
    updatedPackageDetails: Package
): Promise<Package> {
    const shipmentPackagesApi = new ShipmentPackagesApi(configuration);
    console.log(`Updating package ${packageId}...`);
    try {
        // As with other Kibo PUT operations, this performs a full replacement.
        // It's safest to GET the package first, modify it, then PUT it back.
        const updatedPackage = await shipmentPackagesApi.updatePackage({
            shipmentNumber,
            packageId,
            packageDto: updatedPackageDetails,
        });
        console.log("Package updated successfully.");
        return updatedPackage;
    } catch (error) {
        console.error("API Error updating package:", JSON.stringify(error, null, 2));
        throw error;
    }
}

Delete Shipment Package

When You Need This: If you need to completely re-pack a shipment. For example, you decide to split a single-box shipment into two smaller boxes. You would delete the original package and create two new ones. You can only delete a package before a shipping label has been created for it. API Documentation Reference:
// This function deletes a package from a shipment.
async function deletePackage(shipmentNumber: number, packageId: string): Promise<void> {
    const shipmentClient = new ShipmentApi(configuration);
    console.log(`Deleting package ${packageId}...`);
    try {
        // This call returns a 204 No Content on success.
        await shipmentClient.deleteShipmentPackage({
            shipmentNumber,
            packageId,
        });
        console.log("Package deleted successfully.");
    } catch (error) {
        console.error("API Error deleting package:", JSON.stringify(error, null, 2));
        throw error;
    }
}

Multiple Real-World Examples

Example 1: Split a Shipment into Two Packages This advanced workflow shows how to pack a single shipment into two boxes.
async function splitShipmentIntoTwoPackages(shipmentNumber: number) {
    // Assume shipment #10053 has two items:
    const item1 = { productCode: 'MUG-01', quantity: 1 };
    const item2 = { productCode: 'BOOK-02', quantity: 1 };

    // Package 1: Just the mug
    const package1Payload: ModelPackage = {
        packagingType: "Custom",
        measurements: { weight: { value: 2, unit: "lbs" }, /*...dims...*/ },
        items: [item1]
    };
    const package1 = await createNewPackage(shipmentNumber, package1Payload);

    // Package 2: Just the book
    const package2Payload: ModelPackage = {
        packagingType: "Custom",
        measurements: { weight: { value: 3, unit: "lbs" }, /*...dims...*/ },
        items: [item2]
    };
    const package2 = await createNewPackage(shipmentNumber, package2Payload);

    console.log(`Shipment ${shipmentNumber} successfully split into two packages: ${package1.packageId} and ${package2.packageId}`);
}
Example 2, 3, 4, 5: The createNewPackage, updatePackageDetails, and deletePackage functions above serve as complete, runnable examples for each core CRUD operation. The combination in Example 1 also showcases an advanced, multi-step pattern.

Integrating Shipment Packages with Other Kibo Domains

Packages + Fulfillment Workflow

The creation of a package is a key state transition in the fulfillment process. Once all items in a shipment are assigned to one or more packages, the shipment is typically considered “Packed” and is ready for the next step: generating shipping labels. The packageId is a required parameter for the API call that creates a shipping label.

Packages + Customer Experience

The packageId and its associated trackingNumber (which is added to the package object after label generation) are important for the customer experience. This information is used to populate the “Your order has shipped!” email and to provide detailed tracking information on the order status page. Having separate packages allows you to show a customer that their single order is arriving in multiple boxes, each with its own tracking link.

Troubleshooting Your Package Implementation

Reading Kibo Error Messages

interface KiboApiError {
  errorCode: string;      // Specific error codes from apidocs.kibocommerce.com
  message: string;          // Error description
  correlationId: string;  // For support tracking
}
Common Error Codes for Packages:
  • VALIDATION_ERROR: The most common error. This can happen for many reasons: the shipment is not in a “Ready” state, you try to put an item in a package that isn’t in the parent shipment, or the quantities don’t match. The message field is essential for debugging.
  • SHIPMENT_NOT_FOUND: The shipmentNumber you provided does not exist.
  • PACKAGE_NOT_FOUND: The packageId you provided for an update or delete operation does not exist.

Common Development Issues

Issue 1: My call to newShipmentPackage is failing with a VALIDATION_ERROR about the shipment’s state.
  • Why it happens: You can only create packages for shipments that are in the Ready state. If the shipment is still Pending or has already been Fulfilled, the API will reject the request.
  • How to fix it: Before attempting to create a package, your application should first GET the shipment and verify that its status is Ready. If it’s not, you cannot proceed with packing.
Issue 2: I created a package, but now I can’t delete it.
  • Why it happens: The most likely reason is that a shipping label has already been generated for that package. Once a package is associated with a carrier label and tracking number, it becomes part of a financial transaction with the carrier and is effectively “locked” to prevent data integrity issues.
  • How to fix it: The fulfillment workflow must be reversed in the correct order. You would first need to void the shipping label through the carrier integration, which would then allow the package to be deleted. In practice, it’s often easier to work with the shipment as-is unless there is a significant error.