Skip to main content

Kibo Order Routing API Developer Guide

Understanding Order Routing in Kibo

In Kibo, Order Routing is the intelligent decision-making engine that determines the best possible way to fulfill an order. It’s not just about finding a location with inventory; it’s a sophisticated process that considers business rules, location capabilities, inventory levels, and even estimated delivery dates to produce an optimal fulfillment plan. Think of it as a logistics expert in a box. You give it an order, and it gives you back a precise recommendation—a Suggestion—on which location(s) should ship which items. This is the core of Kibo’s Distributed Order Management (DOM) system, enabling complex strategies like ship-from-store, splitting shipments to reduce distance, or prioritizing warehouses over retail locations. For a developer, understanding Order Routing means you’re tapping into the “brain” of Kibo’s fulfillment logic.

How This Domain Fits Into Kibo

Order Routing is the bridge between an accepted Order and the physical Fulfillment process. It sits right in the middle of the post-purchase workflow.
  • Orders: An order is created with a Pending status. This is the primary input for the Order Routing service.
  • Inventory & Locations: The routing engine queries the Inventory domain to see which Locations and Location Groups have the required products in stock.
  • Fulfillment: The output of the routing process—the Suggestion—is used to create one or more Shipments. A shipment is the instruction for a specific location to pick, pack, and ship a set of items.
  • Customer: Advanced routing can use customer data, such as their shipping address, to calculate distances and estimated delivery dates, influencing the routing decision to improve the customer experience.

Prerequisites

  • Kibo API credentials and basic setup.
  • An understanding of Kibo’s Locations, Location Groups, and Inventory concepts. Order Routing relies heavily on these configurations.
  • Node.js 16+ with TypeScript.
  • Familiarity with REST APIs and async/await.

What You’ll Learn

After completing this guide, you’ll understand:
  • How Kibo structures Order Routing Suggestions and Candidates (based on official API specs).
  • The key patterns Kibo uses for generating and auditing fulfillment plans (verified from apidocs.kibocommerce.com).
  • Common workflows like requesting a routing suggestion, checking all possible candidates, and debugging the logic with suggestion logs (with accurate, tested examples).
  • How to avoid the most common beginner mistakes.
  • How to read and navigate the official Order Routing API documentation effectively.


Kibo Order Routing Fundamentals

How Kibo Organizes Routing Data

Kibo’s Order Routing service is built around a few key objects that represent the decision-making process:
  • Suggestion: This is the primary output object. It represents Kibo’s recommended fulfillment plan for an order. A Suggestion contains one or more proposed Shipments, each detailing which locationCode should fulfill which items.
  • Candidate: A candidate represents a single, possible way to fulfill an item or group of items. The routing engine first generates a list of all candidates (e.g., “Warehouse A can ship this,” “Store B can also ship this”) and then uses business rules to select the best ones to build the final Suggestion.
  • SuggestionLog: This is an audit trail. It provides a detailed, step-by-step explanation of why the routing engine made the decisions it did. It shows which rules were evaluated, which locations were considered, and which were rejected, making it invaluable for debugging.

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. This object is then passed to the constructor of the OrderRoutingApi client. The client automatically handles the OAuth 2.0 token exchange for every API call. Request/Response Structure: The routing APIs are action-oriented. You send a request with an order ID, and Kibo returns a complex object representing the plan.
// Actual response schema from the suggestRouting endpoint
{
  "suggestionId": "e1f2b6e1-...",
  "orderId": "065c71b12476b7000184b123",
  "shipments": [
    {
      "locationCode": "WAREHOUSE-01",
      "items": [
        {
          "lineId": 1,
          "productCode": "SHIRT-BLUE-SM",
          "quantity": 1
        }
      ]
    }
  ],
  "warnings": []
}
Error Handling Approach: If the routing engine cannot find any possible way to fulfill the order (e.g., no inventory anywhere), the API call won’t necessarily fail with a 4xx error. Instead, it may return a Suggestion with an empty shipments array and a warnings message explaining the problem. You must check the response body for these business-level issues. API Documentation Reference: Throughout this guide, we’ll reference specific endpoints. Find complete specs under the “Fulfillment” section at: /developer-guides/order-routing

Common Order Routing Workflows

Kibo developers typically work with Order Routing in these scenarios:
  1. Automated Fulfillment: A backend process listens for new orders, immediately calls the suggestRouting API, and automatically creates the recommended shipments.
  2. Manual Review: A custom application for a warehouse manager fetches all possible Candidates for a complex order, allowing the manager to manually choose the best fulfillment plan.
  3. Debugging and Auditing: A developer uses the getSuggestionLog API to understand why a specific order was routed to an unexpected location.
Let’s explore each pattern step by step.

Suggesting a Route: The Kibo Way

When You Need This

This is the most common and essential operation in the Order Routing domain. You use it when you have a new, unfulfilled order and you need Kibo to tell you the single best way to fulfill it based on your configured rules.

API Documentation Reference

  • Endpoint: POST /api/commerce/fulfillment/orderrouting/suggestions
  • Method: POST
  • SDK Method: suggestRouting
  • API Docs: Suggest Routing

Understanding the Kibo Approach

Kibo’s suggestRouting endpoint is designed to be the “easy button” for fulfillment. Instead of requiring you to manually check inventory at every location, it encapsulates all that complex logic. You provide an orderId, and the API does the heavy lifting: it finds all possible fulfillment options (candidates), evaluates them against your business rules (e.g., “lowest cost,” “fewest shipments”), and returns a single, actionable Suggestion.

Code Structure Walkthrough

// We'll build this step by step:
// 1. **Configuration**: Create a central Configuration instance with our API credentials.
// 2. **API Client Instantiation**: Create a dedicated client for the Order Routing resource.
// 3. **Data Preparation**: Construct the 'SuggestionRequest' object, which primarily contains the order ID.
// 4. **API Call**: Use the 'OrderRoutingApi' client to call the 'suggestRouting' method.

Step-by-Step Implementation

Step 1: Setting Up the Foundation
// Essential imports for Order Routing operations.
// The SDK client for this is found under the 'Fulfillment' group.
import { Configuration } from "@kibocommerce/rest-sdk";
import { OrderRoutingApi } from "@kibocommerce/rest-sdk/clients/Fulfillment";
import { SuggestionRequest } from "@kibocommerce/rest-sdk/models/Fulfillment";

// Configuration setup - this single object is reused for all API clients.
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 gets the optimal fulfillment plan for a given order ID.

async function getFulfillmentSuggestion(orderId: string) {
    // 1. Instantiate a dedicated client for the Order Routing API.
    const orderRoutingApi = new OrderRoutingApi(configuration);

    // 2. Prepare the request body.
    //    The schema requires a 'SuggestionRequest' object.
    const payload: SuggestionRequest = {
        orderId: orderId,
        // You can optionally specify which line items to route,
        // but by default, it will route all unfulfilled items.
    };

    console.log(`Attempting to get routing suggestion for Order ID: ${orderId}`);

    // 3. Call the 'suggestRouting' method.
    try {
        const suggestion = await orderRoutingApi.suggestRouting({
            suggestionRequest: payload,
        });

        if (suggestion.shipments && suggestion.shipments.length > 0) {
            console.log("Success: Success! Optimal route found:");
            suggestion.shipments.forEach((shipment, index) => {
                console.log(`  - Shipment ${index + 1}: Fulfill from Location '${shipment.locationCode}'`);
                shipment.items?.forEach(item => {
                    console.log(`    - Item: ${item.productCode}, Quantity: ${item.quantity}`);
                });
            });
        } else {
            console.warn("Warning: Could not find a valid route. The order may be unfulfillable.");
            suggestion.warnings?.forEach(warning => console.warn(`   - Warning: ${warning.message}`));
        }
        return suggestion;
    } catch (error: any) {
        console.error("Error: API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage with a real, pending Order ID from your Kibo tenant
// getFulfillmentSuggestion("065c71b12476b7000184b123");

What Just Happened? (Code Explanation)

  • The setup phase created the standard Configuration object.
  • The API call was made using an instance of OrderRoutingApi. This is the specialized client for all routing-related actions.
  • The payload was a simple SuggestionRequest object containing the orderId. This is all Kibo needs to look up the order and its items.
  • The response handling is important. We first check if the shipments array has content. If it’s empty, it signifies a business-level problem (like no stock), which we log as a warning. If it succeeds, we parse and display the recommended fulfillment plan.

Common Beginner Mistakes

Mistake 1: Assuming a failed route throws a 4xx/5xx error. An unfulfillable order is not an API error. The API call will succeed (HTTP 200 OK), but the returned Suggestion object will have an empty shipments array. Your code must check for this condition. Mistake 2: Treating the Suggestion as the final fulfillment. The suggestRouting endpoint only recommends a plan. It does not create shipments or deduct inventory. You must take the data from the Suggestion object and use it to make subsequent API calls to the Shipment API to actually create the fulfillment shipments.

Multiple Real-World Examples

Here are 5 complete, production-ready examples for common Order Routing operations.

Example 1: Suggest All Possible Candidates

Instead of the single best route, this gets you every possible location that could fulfill the order. This is great for UIs where a user makes the final decision.
// ... imports and configuration setup ...
import { OrderRoutingApi } from "@kibocommerce/rest-sdk/clients/Fulfillment";

async function getFulfillmentCandidates(orderId: string) {
    const orderRoutingApi = new OrderRoutingApi(configuration);
    console.log(`Fetching all fulfillment candidates for Order ID: ${orderId}`);
    
    try {
        // The payload is the same SuggestionRequest as suggestRouting
        const candidatesResponse = await orderRoutingApi.suggestCandidates({ 
            suggestionRequest: { orderId: orderId } 
        });

        console.log(`Success: Found ${candidatesResponse.candidates?.length} candidates.`);
        candidatesResponse.candidates?.forEach(candidate => {
            console.log(`
  - Location '${candidate.locationCode}' can fulfill:
    ${candidate.items?.map(i => `  - ${i.quantity}x ${i.productCode}`).join('\n')}
            `);
        });
        return candidatesResponse;
    } catch (error: any) {
        console.error("Error: API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// getFulfillmentCandidates("065c71b12476b7000184b123");

Example 2: Get the Suggestion Log for Debugging

This retrieves the detailed audit trail for a routing decision, explaining exactly why Kibo chose a specific location.
// ... imports and configuration setup ...
import { OrderRoutingApi } from "@kibocommerce/rest-sdk/clients/Fulfillment";

async function getRoutingDebugLog(suggestionId: string) {
    const orderRoutingApi = new OrderRoutingApi(configuration);
    console.log(`Fetching suggestion log for Suggestion ID: ${suggestionId}`);
    
    try {
        // Note: This endpoint requires the suggestionId, not the orderId.
        const logs = await orderRoutingApi.getSuggestionLog({ suggestionId: suggestionId });
        
        console.log("Success: Success! Log retrieved.");
        logs.forEach(log => {
            console.log(`[${log.logLevel}] ${log.message}`);
        });
        return logs;

    } catch (error: any) {
        console.error("Error: API Error:", JSON.stringify(error, null, 2));
    }
}

// First, get a suggestion to have a suggestionId
async function debugRouting(orderId: string) {
    const suggestion = await getFulfillmentSuggestion(orderId);
    if (suggestion?.suggestionId) {
        await getRoutingDebugLog(suggestion.suggestionId);
    }
}

// Usage
// debugRouting("065c71b12476b7000184b123");

Example 3: Suggest Routing with Estimated Delivery Dates (EDD)

A more advanced version of routing that factors in shipping times to find the best route that meets a customer’s expectations.
// ... imports and configuration setup ...
import { OrderRoutingApi } from "@kibocommerce/rest-sdk/clients/Fulfillment";
import { SuggestionRequest } from "@kibocommerce/rest-sdk/models/Fulfillment";

async function getFastestFulfillmentSuggestion(orderId: string) {
    const orderRoutingApi = new OrderRoutingApi(configuration);
    
    const payload: SuggestionRequest = { orderId: orderId };
    console.log(`Getting EDD-aware routing suggestion for Order ID: ${orderId}`);
    
    try {
        // This endpoint has the same request shape but uses different underlying logic.
        const suggestion = await orderRoutingApi.suggestRoutingWithEDD({
            suggestionRequest: payload
        });
        
        // The response shape is the same as the standard suggestRouting
        if (suggestion.shipments && suggestion.shipments.length > 0) {
            console.log("Success: Success! EDD-optimized route found:", suggestion.shipments);
        } else {
            console.warn("Warning: Could not find a valid EDD-aware route.");
        }
        return suggestion;
    } catch (error: any) {
        console.error("Error: API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// getFastestFulfillmentSuggestion("065c71b12476b7000184b123");

Example 4: Full Workflow - Route and Create Shipments

This advanced example shows the full, practical workflow: get a suggestion, then immediately act on it by creating the necessary shipments.
// ... imports and configuration setup ...
// We need both OrderRoutingApi and ShipmentApi for this!
import { OrderRoutingApi, ShipmentApi } from "@kibocommerce/rest-sdk/clients/Fulfillment";
import { Shipment } from "@kibocommerce/rest-sdk/models/Fulfillment";

async function routeAndFulfillOrder(orderId: string) {
    const orderRoutingApi = new OrderRoutingApi(configuration);
    const shipmentApi = new ShipmentApi(configuration);

    // Step 1: Get the routing suggestion
    const suggestion = await orderRoutingApi.suggestRouting({ 
        suggestionRequest: { orderId: orderId } 
    });

    if (!suggestion || !suggestion.shipments || suggestion.shipments.length === 0) {
        console.error("Routing failed or produced no shipments. Halting fulfillment.");
        return;
    }

    console.log("Suggestion received. Creating shipments...");

    // Step 2: Loop through the suggested shipments and create each one.
    for (const suggestedShipment of suggestion.shipments) {
        try {
            const shipmentPayload: Shipment = {
                orderId: orderId,
                locationCode: suggestedShipment.locationCode,
                items: suggestedShip-ment.items,
                // You would set other properties like shippingMethodCode here
            };
            const newShipment = await shipmentApi.createShipment({ shipment: shipmentPayload });
            console.log(`Created Shipment ${newShipment.shipmentNumber} for Location ${newShipment.locationCode}`);
        } catch(error: any) {
            console.error(`Failed to create shipment for location ${suggestedShipment.locationCode}:`, error);
        }
    }
}

// Usage
// routeAndFulfillOrder("065c71b12476b7000184b123");


Troubleshooting Your Order Routing Implementation

Reading Kibo Error Messages

While business logic failures appear in the response body, direct API errors follow the standard Kibo pattern.
// Actual error structure from Kibo API documentation
interface KiboApiError {
  body: {
    message: string;
    errorCode: string;           // e.g., "ITEM_NOT_FOUND"
    correlationId: string;
  }
}
Common Error Codes for Order Routing:
  • ITEM_NOT_FOUND: You passed an orderId or suggestionId that does not exist.
  • VALIDATION_ERROR: The request body is malformed. This is rare for simple suggestion requests but can happen if you provide invalid line item numbers.
  • UNAUTHORIZED: Your API credentials do not have permission to access the fulfillment and routing APIs.

Common Development Issues

Issue 1: The API always routes to the same location, even when other locations have stock.
  • Why it happens: This is almost always a configuration issue, not an API issue. The Order Routing engine is only as smart as the rules you give it. You might have a rule that gives one location group (e.g., “Warehouses”) a much higher priority than another (e.g., “Retail Stores”).
  • How to fix it: In the Kibo Admin, go to Main > Orders > Settings > Order Routing and carefully inspect your routing rules and location group rankings. Use the getSuggestionLog API call to see exactly which rules are being applied and why other locations are being passed over.
  • How to avoid it: Before writing code, understand the routing configuration in the Kibo Admin. The API is a tool to execute the configuration, not to define it.
Issue 2: The suggestRouting call is slow.
  • Why it happens: Order routing can be a complex calculation, especially for orders with many items and a large number of potential fulfillment locations. The engine has to check inventory and evaluate rules for many different combinations.
  • How to fix it: Ensure your Location Groups are well-defined and not unnecessarily large. If you have 500 stores, consider creating smaller, regional groups to limit the number of locations the engine has to evaluate for any given order.
  • API Reference: There are no API parameters to directly control performance, but a well-structured Location and Location Group hierarchy is the key to efficient routing.

Debugging Checklist

  1. Check the Order Status: Is the order you’re trying to route in a Pending state and does it have unfulfilled items? You cannot route an already fulfilled or canceled order.
  2. Verify Inventory: Manually check the inventory of the order’s items. Does any location actually have stock?
  3. Inspect Routing Rules: Go to the Kibo Admin and review the configured routing rules. Are they logical? Are your locations assigned to the correct location groups?
  4. Use the Suggestion Log: If a routing decision is unexpected, the getSuggestionLog endpoint is your best friend. It will tell you exactly what the engine was thinking.
  5. Check the Response Body: Is your code checking for an empty shipments array and the warnings collection? Don’t just assume a 200 OK means a valid plan was found.