Skip to main content

Kibo Pricing API Developer Guide

Understanding Pricing in Kibo

In Kibo, pricing is a powerful, standalone concept that is decoupled from the core product. Unlike platforms where a product has a single, fixed price attribute, a Kibo product has no inherent price. Instead, prices are defined in Price Lists, and products are assigned prices within those lists. This architecture is incredibly flexible. It allows you to create an unlimited number of price lists for different contexts without ever duplicating a product. You can have separate price lists for:
  • Different currencies (USD Price List, EUR Price List)
  • B2B customers with negotiated contract rates (Contract A Price List)
  • VIP customer segments (Gold Member Price List)
  • Time-bound sales and promotions (Black Friday Sale Price List)
The Kibo platform automatically “resolves” the correct price for a shopper based on their context (which site they’re on, their customer account, etc.), making it seamless to manage complex pricing strategies.

How This Domain Fits Into Kibo

The Pricing domain is a foundational service that is consulted throughout the entire customer journey.
  • Catalog: When a product is displayed on a category or search results page, Kibo’s platform determines the correct price list for the shopper and shows the appropriate price.
  • Cart & Checkout: As items are added to the cart, the Pricing engine calculates the subtotal. This same engine is what applies discounts from the Promotion domain.
  • Customer: Customer accounts or B2B accounts can be “entitled” to specific price lists, giving them access to exclusive or negotiated pricing.
  • Orders: The final, resolved prices for each item are captured and stored on the order record at the time of purchase.

Prerequisites

  • Kibo API credentials with Catalog Administration permissions.
  • 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 Price List and Price List Entry data (based on official API specs).
  • The key patterns Kibo uses for all pricing CRUD operations (verified from apidocs.kibocommerce.com).
  • Common workflows like creating sale lists and bulk-updating prices (with accurate, tested examples).
  • How to avoid the most common beginner mistakes.
  • How to read and navigate the official API documentation for pricing.


Kibo Pricing Fundamentals

How Kibo Organizes Pricing Data

Kibo’s Pricing data model is built on a simple but powerful hierarchy:
  • PriceList: This is the container object for a set of prices. It acts as a named bucket. Key properties include:
    • priceListCode: A unique, user-defined string identifier (e.g., USD-RETAIL or VIP-PRICING). You’ll use this code in almost every API call.
    • name: A human-readable name for the list (e.g., “USD Retail Prices”).
    • enabled: A boolean to activate or deactivate the entire price list.
  • PriceListEntry: This is the actual price for a single product within a price list. A PriceList can contain thousands of these entries. Key properties include:
    • productCode: The product this price applies to.
    • currencyCode: The currency of the price (e.g., “USD”).
    • price: The final price a customer pays. If a salePrice is active, this is ignored.
    • salePrice: An optional, lower price that takes precedence over the price.
    • startDate / endDate: Optional ISO 8601 date-time strings that define when the price entry is active. This is perfect for scheduling sales.

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 PriceListsApi client. The client will automatically handle the OAuth 2.0 token exchange for every API call. Request/Response Structure: Many pricing operations are designed for bulk updates. When adding or updating price list entries, you send an array of entry objects in the request body. The API will process them as a batch.
// Actual request schema for adding Price List Entries
// POST /api/commerce/catalog/admin/pricelists/{priceListCode}/entries
[
  {
    "productCode": "SHIRT-BLUE-SM",
    "currencyCode": "USD",
    "price": 24.99,
    "msrp": 30.00
  },
  {
    "productCode": "PANTS-BLK-32",
    "currencyCode": "USD",
    "price": 55.00
  }
]
Error Handling Approach: If an API call fails, the SDK throws a structured error. For pricing, a common error is ITEM_ALREADY_EXISTS when trying to create a PriceList with a priceListCode that’s already in use. API Documentation Reference: Throughout this guide, we’ll reference specific endpoints. Find complete specs under the “Catalog Administration” section at: /api-reference/pricelist/get-price-lists

Common Pricing Workflows

Kibo developers typically work with Pricing in these scenarios:
  1. System Integration: Syncing prices from an external ERP or PIM system into Kibo by creating and updating price lists.
  2. Promotional Pricing: Creating a new, temporary price list for a holiday sale and scheduling it to activate and deactivate automatically.
  3. B2B/Contract Pricing: Managing dedicated price lists for specific B2B accounts with negotiated rates.
Let’s explore each pattern step by step.

Creating a Price List: The Kibo Way

When You Need This

This is the first step for any new pricing strategy. You need a container to hold your prices, whether it’s for a new currency, a new customer segment, or a temporary sale. This operation creates that empty container.

API Documentation Reference

  • Endpoint: POST /api/commerce/catalog/admin/pricelists
  • Method: POST
  • SDK Method: addPriceList
  • API Docs: Add Price List

Understanding the Kibo Approach

Kibo separates the creation of the price list (the container) from the act of adding prices to it. This allows you to set up the structure and metadata of your price list first. The priceListCode you define here becomes the unique key for all future operations, like adding or updating the prices within it.

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 Price List resource.
// 3. **Data Preparation**: Construct the 'PriceList' request body object according to the API schema.
// 4. **API Call**: Use the 'PriceListsApi' client to call the 'addPriceList' method.

Step-by-Step Implementation

Step 1: Setting Up the Foundation
// Essential imports for Pricing operations.
// The SDK client for this is found under the 'CatalogAdministration' group.
import { Configuration } from "@kibocommerce/rest-sdk";
import { PriceListsApi } from "@kibocommerce/rest-sdk/clients/CatalogAdministration";
import { CatalogAdminsPriceList } from "@kibocommerce/rest-sdk/clients/CatalogAdministration";

// Configuration setup - this single object is reused for all API clients.
// Pricing management requires administrative permissions.
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, empty price list for a fall sale.

async function createNewPriceList() {
    // 1. Instantiate a dedicated client for the Price Lists API.
    const priceListsApi = new PriceListsApi(configuration);

    // 2. Prepare the request body.
    //    This object must match the 'CatalogAdminsPriceList' schema.
    const payload: CatalogAdminsPriceList = {
        priceListCode: "FALL_SALE_2025",
        name: "Fall Sale 2025",
        enabled: true,
        resolvable: true, // 'resolvable' means the platform can automatically select this list for shoppers.
        // 'validSites' can be used to limit this list to specific sites in a multi-site environment.
    };

    console.log(`Attempting to create price list: ${payload.name}`);

    // 3. Call the 'addPriceList' method on the client.
    try {
        const newPriceList = await priceListsApi.addPriceList({
            catalogAdminsPriceList: payload
        });
        console.log("Success: New price list created:", JSON.stringify(newPriceList, null, 2));
        return newPriceList;
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
        if (error.body?.errorCode === 'ITEM_ALREADY_EXISTS') {
            console.error(`Error: A price list with code '${payload.priceListCode}' already exists.`);
        }
    }
}

createNewPriceList();

What Just Happened? (Code Explanation)

  • The setup phase created the Configuration object, which is standard for all SDK interactions.
  • The API call used an instance of PriceListsApi to interact with the pricing endpoints.
  • The payload was a PriceList object. We defined our own unique priceListCode which acts as its permanent ID. We also set resolvable to true, which is important for allowing the storefront to use this price list.
  • The response handling uses a try...catch block. On success, Kibo returns the full price list object we just created. On failure, we specifically check for the ITEM_ALREADY_EXISTS error to give a more user-friendly message.

Common Beginner Mistakes

Mistake 1: Trying to add prices at the same time as creating the list. The addPriceList endpoint only creates the container. You cannot include an array of PriceListEntry objects in its payload. Adding prices is a separate, subsequent API call. Mistake 2: Not setting resolvable to true. If a price list is not resolvable, the Kibo platform won’t consider it when determining which price to show a shopper on the storefront. It can still be accessed directly via the API, but it won’t be used automatically. For most B2C use cases, you want this to be true.

Multiple Real-World Examples

Here are 5 complete, production-ready examples for common Price List CRUD operations.

Example 1: Bulk Add Prices to a Price List

After creating a price list, you need to populate it. This is the most common “write” operation.
// ... imports and configuration setup ...
import { PriceListsApi } from "@kibocommerce/rest-sdk/clients/CatalogAdministration";
import { PriceListEntry } from "@kibocommerce/rest-sdk/models/CatalogAdministration";

async function addPricesToSaleList(priceListCode: string) {
    const priceListsApi = new PriceListsApi(configuration);
    
    // The payload is an array of PriceListEntry objects.
    const priceEntries: PriceListEntry[] = [
        {
            productCode: "SHIRT-BLUE-SM",
            currencyCode: "USD",
            price: 19.99, // The sale price
        },
        {
            productCode: "PANTS-BLK-32",
            currencyCode: "USD",
            price: 45.00,
        },
    ];

    console.log(`Adding ${priceEntries.length} prices to list '${priceListCode}'...`);
    try {
        // NOTE: This is a bulk operation. It has no return body on success (204 No Content).
        await priceListsApi.addPriceListEntries({ 
            priceListCode: priceListCode,
            priceListEntry: priceEntries,
            // You can set 'throwErrorOnInvalidEntries' to true to make the whole batch fail if one entry is bad.
        });
        console.log("Success: Prices added to the list.");
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// addPricesToSaleList("FALL_SALE_2025");

Example 2: Get Price List Entries with Pagination

This shows how to read the prices contained within a list.
// ... imports and configuration setup ...
import { PriceListsApi } from "@kibocommerce/rest-sdk/clients/CatalogAdministration";

async function getPricesFromList(priceListCode: string) {
    const priceListsApi = new PriceListsApi(configuration);
    console.log(`Fetching prices from list '${priceListCode}'...`);
    
    try {
        const entriesCollection = await priceListsApi.getPriceListEntries({
            priceListCode: priceListCode,
            pageSize: 5, // Fetching in pages of 5
            startIndex: 0
        });

        console.log(`Success: Found ${entriesCollection.totalCount} total entries.`);
        entriesCollection.items?.forEach(entry => {
            console.log(`  - ${entry.productCode}: ${entry.price} ${entry.currencyCode}`);
        });
        return entriesCollection;
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// getPricesFromList("FALL_SALE_2025");

Example 3: Bulk Update Existing Prices

Use this to change prices that are already in a price list.
// ... imports and configuration setup ...
import { PriceListsApi } from "@kibocommerce/rest-sdk/clients/CatalogAdministration";
import { PriceListEntry } from "@kibocommerce/rest-sdk/models/CatalogAdministration";

async function updatePricesInSaleList(priceListCode: string) {
    const priceListsApi = new PriceListsApi(configuration);

    const updatedPriceEntries: PriceListEntry[] = [
        {
            productCode: "SHIRT-BLUE-SM",
            currencyCode: "USD",
            price: 18.99, // Further reduction!
        }
    ];

    console.log(`Updating ${updatedPriceEntries.length} prices in list '${priceListCode}'...`);
    try {
        await priceListsApi.updatePriceListEntries({
            priceListCode: priceListCode,
            priceListEntry: updatedPriceEntries
        });
        console.log("Success: Prices updated.");
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// updatePricesInSaleList("FALL_SALE_2025");

Example 4: Schedule a Future Sale Price

This example shows how to use startDate and endDate to create a price that only becomes active during a specific window.
// ... imports and configuration setup ...
import { PriceListsApi } from "@kibocommerce/rest-sdk/clients/CatalogAdministration";
import { PriceListEntry } from "@kibocommerce/rest-sdk/models/CatalogAdministration";

async function scheduleHolidayPrice(priceListCode: string) {
    const priceListsApi = new PriceListsApi(configuration);

    const futureSalePrice: PriceListEntry[] = [{
        productCode: "PANTS-BLK-32",
        currencyCode: "USD",
        price: 39.99,
        // Dates must be in ISO 8601 format
        startDate: "2025-11-28T00:00:00-06:00", // Start of Black Friday (US Central Time)
        endDate: "2025-12-01T23:59:59-06:00",   // End of Cyber Monday
    }];

    console.log(`Scheduling future price in list '${priceListCode}'...`);
    try {
        // We use the 'update' method as it performs an "upsert" for entries.
        await priceListsApi.updatePriceListEntries({
            priceListCode: priceListCode,
            priceListEntry: futureSalePrice
        });
        console.log("Success: Future sale price has been scheduled.");
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// scheduleHolidayPrice("FALL_SALE_2025");

Example 5: Clean Up - Delete Prices and the Price List

This demonstrates the full lifecycle: removing specific prices from a list and then deleting the list itself.
// ... imports and configuration setup ...
import { PriceListsApi } from "@kibocommerce/rest-sdk/clients/CatalogAdministration";

async function cleanupPriceList(priceListCode: string) {
    const priceListsApi = new PriceListsApi(configuration);
    
    // Step 1: Delete specific entries from the list.
    // The payload is an array of product codes to delete.
    const productsToDelete = ["SHIRT-BLUE-SM", "PANTS-BLK-32"];
    console.log(`Deleting ${productsToDelete.length} entries from list '${priceListCode}'...`);
    try {
        await priceListsApi.deletePriceListEntries({
            priceListCode: priceListCode,
            productCode: productsToDelete
            // Note: The SDK parameter is 'productCode' but it accepts an array.
        });
        console.log("Entries deleted.");
    } catch (error: any) {
        console.error("Error deleting entries:", JSON.stringify(error, null, 2));
        // We might want to stop if this fails
        return;
    }

    // Step 2: Delete the now-empty price list container.
    console.log(`Deleting price list '${priceListCode}'...`);
    try {
        await priceListsApi.deletePriceList({ priceListCode: priceListCode });
        console.log("Price list deleted successfully.");
    } catch (error: any) {
        console.error("Error deleting price list:", JSON.stringify(error, null, 2));
    }
}

// Usage
// cleanupPriceList("FALL_SALE_2025");


Troubleshooting Your Pricing Implementation

Reading Kibo Error Messages

// Actual error structure from Kibo API documentation
interface KiboApiError {
  body: {
    message: string;
    errorCode: string;           // e.g., "ITEM_ALREADY_EXISTS"
    correlationId: string;
    items?: Array<{             // Present for bulk validation errors
        name: string;
        errorCode: string;
        message: string;
    }>
  }
}
Common Error Codes for Pricing:
  • ITEM_ALREADY_EXISTS: You tried to addPriceList with a priceListCode that is already in use.
  • ITEM_NOT_FOUND: You tried to operate on a priceListCode that does not exist.
  • VALIDATION_ERROR: The request body is malformed. When performing bulk entry updates, the items array in the error response will tell you which product code or price was invalid.

Common Development Issues

Issue 1: My price updates aren’t appearing on the storefront immediately.
  • Why it happens: Kibo’s platform has several layers of caching to ensure high performance. Price list information is cached, so changes made via the API might not be reflected for a few minutes until the cache expires.
  • How to fix it: For immediate testing, you can often trigger a cache clear in the Kibo Admin under System > Caching. For automated processes, you can either wait for the cache TTL (Time To Live) to expire naturally or, for advanced use cases, include a special X-Vol-Cache-Flush: true header in your API call to request a cache invalidation.
  • How to avoid it: Be aware that caching is a feature. For most bulk updates that run overnight, this is not an issue. Factor in a potential delay of a few minutes for changes to propagate.
Issue 2: My bulk update of 1,000 prices is failing, but I don’t know which one is wrong.
  • Why it happens: A single invalid productCode or a malformed price in a large batch will cause the entire API call to fail (if throwErrorOnInvalidEntries is true).
  • How to fix it: Inspect the items array within the error response body. Kibo will often report which specific entry in your payload caused the validation failure. Also, consider sending your updates in smaller chunks (e.g., 100-200 entries per call) to make it easier to isolate a bad record.
  • API Reference: Review the schema for PriceListEntry carefully to ensure all your data types are correct (e.g., price is a number, not a string).