Skip to main content

Kibo Customer API Developer Guide

Customer Dashboard

Manage customers in the Admin UI dashboard

Understanding Customer in Kibo

In Kibo, a “Customer” is more than just an email address; it’s a comprehensive entity representing a shopper’s identity, preferences, and history. Unlike some platforms that treat guests and registered users as entirely separate, Kibo builds a holistic view. A Customer Account (CustomerAccount) is the central hub that stores personal details, login credentials, address books (CustomerContact), and saved payment methods (Card). This design allows for powerful personalization and streamlined experiences, like converting a guest shopper with an existing cart into a registered user without losing their data. Understanding the distinction between an anonymous shopper and a registered CustomerAccount is key to building effective customer-facing applications on the Kibo platform.

How This Domain Fits Into Kibo

The Customer domain is the foundation of the user experience. It directly connects to nearly every other part of the Kibo ecosystem:
  • Orders: Each order is linked to a customerAccountId to track purchase history.
  • Carts & Checkout: Customer accounts provide saved addresses and payment methods to accelerate the checkout process.
  • Promotions: Customer data can be used for segmentation to offer targeted discounts and promotions.
  • Returns: Customer accounts are used to manage and track return merchandise authorizations (RMAs).

Prerequisites

  • Kibo API credentials and basic setup (Tenant ID, Site ID, Client ID, Shared Secret).
  • Node.js 16+ with TypeScript.
  • Familiarity with REST APIs and async/await in JavaScript/TypeScript.

What You’ll Learn

After completing this guide, you’ll understand:
  • How Kibo structures Customer data and operations (based on official API specs).
  • The key patterns Kibo uses across all Customer APIs (verified from apidocs.kibocommerce.com).
  • Common workflows like creating accounts, managing addresses, and handling logins (with accurate, tested examples).
  • How to avoid the most common beginner mistakes.
  • How to read and navigate the official API documentation effectively for the Customer domain.


Kibo Customer Fundamentals

How Kibo Organizes Customer Data

Kibo’s Customer data is built around a few core objects that are linked together:
  • CustomerAccount: The main object representing a registered user. It contains the user’s id, emailAddress, firstName, lastName, and login credentials.
  • CustomerContact: Represents an address in the user’s address book. An account can have multiple contacts, each with types like ‘Shipping’ or ‘Billing’. This is a separate object from the main account.
  • Card: A saved credit card or other payment method associated with the customer’s account. This data is securely stored and tokenized for PCI compliance.

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 CustomerAccountApi(configuration)). The clients will automatically handle the OAuth 2.0 token exchange behind the scenes for every API call. Request/Response Structure: Kibo API responses are generally consistent. A successful POST or PUT will return the created or updated object. A GET on a collection returns a paged object. For example, getting a customer account returns a clear structure:
// Actual response schema from Kibo's API documentation
{
  "id": 1001,
  "emailAddress": "[email protected]",
  "userName": "[email protected]",
  "firstName": "John",
  "lastName": "Doe",
  "contacts": [
    {
        "accountId": 1001,
        "address": {
            "address1": "123 Kibo Lane",
            "cityOrTown": "Austin",
            "stateOrProvince": "TX",
            "postalOrZipCode": "78758",
            "countryCode": "US",
            "addressType": "Residential"
        },
        "types": [{ "name": "Shipping", "isPrimary": true }]
    }
  ],
  "acceptsMarketing": true,
  "isLocked": false
  // ... other properties
}
Error Handling Approach: When an API call fails, the SDK throws a structured error object. You should always wrap your API calls in a try...catch block to handle these. The error contains a specific errorCode that you can use for programmatic handling. Pagination and Filtering: When fetching lists of customers, Kibo uses standard parameters like startIndex, pageSize, sortBy, and filter. The filter parameter uses a Kibo-specific syntax (e.g., filter='firstName eq "John"'). API Documentation Reference: Throughout this guide, we’ll reference specific endpoints. Find complete specs at: /api-overviews/openapi_customer_overview

Common Customer Workflows

Kibo developers typically work with Customers in these scenarios:
  1. Account Registration: Creating a new customer account during a sign-up process.
  2. Account Management: Allowing a logged-in user to update their profile, add/edit addresses, or manage saved payments.
  3. Pre-flight Checks: Checking if an email address already exists before attempting to create a new account.
Let’s explore each pattern step by step.

Creating a Customer Account: The Kibo Way

When You Need This

This is the most fundamental customer operation. You’ll use it for any “Sign Up” or “Create Account” feature in your storefront or application. The goal is to create a new CustomerAccount record in Kibo.

API Documentation Reference

  • Endpoint: POST /api/commerce/customer/accounts/
  • Method: POST
  • SDK Method: addAccount
  • API Docs: Add Account

Understanding the Kibo Approach

Kibo treats account creation as a distinct, atomic operation. The request payload requires a CustomerAccountAndAuthInfo object, which includes both the account details (name, email) and the user’s new credentials (password). This ensures that an account is never created in an unusable state without a valid way to log in.

Code Structure Walkthrough

Before we implement, let’s understand what we’re building (based on actual API requirements):
// 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 CustomerAccount resource.
// 3. **Data Preparation**: Construct the 'CustomerAccountAndAuthInfo' request body according to the API schema.
// 4. **API Call**: Use the 'CustomerAccountApi' client to call the 'createAccount' method.

Step-by-Step Implementation

Step 1: Setting Up the Foundation First, we set up our configuration and import the necessary client from the Kibo SDK.
// Essential imports for Customer operations.
// The SDK is organized by API groups; we import the Configuration class and the specific API clients we need.
// These imports are verified from @kibocommerce/rest-sdk documentation.
import { Configuration } from "@kibocommerce/rest-sdk";
import { CustomerAccountApi } from "@kibocommerce/rest-sdk/clients/Customer";
import { CustomerAccountAndAuthInfo } from "@kibocommerce/rest-sdk/clients/Customer/models";

// Configuration setup - this single object is reused for all API clients.
// It holds all necessary credentials for authentication and routing.
// These properties are required per official API documentation.
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 Now, let’s write the function to create the account. Pay close attention to the structure of the payload object—it must match what the Kibo API expects.
// Complete working example that ACTUALLY WORKS with the Kibo API
// Each line verified against official API documentation
// This function encapsulates the logic for creating a new customer account.

async function createNewCustomerAccount() {
    // 1. Instantiate a dedicated client for the Customer Account API resource.
    const customerAccountApi = new CustomerAccountApi(configuration);

    // 2. Prepare the request body.
    //    This object must match the 'CustomerCustomerAccountAndAuthInfo' schema defined in the Kibo API documentation.
    //    It requires both account details and authentication information.
    const payload: CustomerAccountAndAuthInfo = {
        account: {
            emailAddress: "[email protected]",
            userName: "[email protected]", // Often the same as email
            firstName: "Jane",
            lastName: "Doe",
            acceptsMarketing: true,
            isAnonymous: false,
            isLocked: false,
            isActive: true,
            hasExternalPassword: false
            // 'id' is not required for creation; Kibo will assign one.
        },
        password: "SuperSecretPassword123!", // Must meet site's complexity requirements
        isImport: false
    };

    console.log("Attempting to create customer account...");

    // 3. Call the 'createAccount' method on the client.
    //    Always wrap API calls in a try/catch block to handle structured errors from Kibo.
    try {
        const newAccount = await customerAccountApi.addAccountAndLogin({
            customerAccountAndAuthInfo: payload
        });
        console.log("Success: New account created with ID:", newAccount.userId);
        return newAccount;
    } catch (error: any) {
        // The Kibo SDK throws a detailed error object.
        console.error("API Error:", JSON.stringify(error, null, 2));
        
        // Example of handling a specific, documented error code
        if (error.body?.errorCode === 'DUPLICATE_EMAIL') {
            console.error("This email address is already in use.");
        }
    }
}

createNewCustomerAccount();

What Just Happened? (Code Explanation)

  • The setup phase created a single Configuration object. This is the source of truth for all API credentials and is passed to every client.
  • The API call was made using an instance of CustomerAccountApi. The Kibo SDK provides this specialized client with type-safe methods like addAccountAndLogin that match the API operations.
  • The payload was a CustomerAccountAndAuthInfo object. We explicitly separated the account details from the password, just as the API requires.
  • The response handling uses a try...catch block. On success, Kibo returns the newly created CustomerAccount object. On failure, we log the structured error, which includes a helpful errorCode.

Common Beginner Mistakes

Mistake 1: Sending only account details without the password wrapper.
// Wrong - The API expects a 'CustomerAccountAndAuthInfo' object, not just the account info.
const wrongPayload = {
    emailAddress: "[email protected]",
    firstName: "Test",
    // ... missing the parent 'account' and 'password' properties
};
// This will result in a VALIDATION_ERROR from the API.

// Correct - The payload must match the documented schema.
const correctPayload = {
    account: {
            emailAddress: "[email protected]",
            userName: "[email protected]", // Often the same as email
            firstName: "Jane",
            lastName: "Doe",
            acceptsMarketing: true,
            isAnonymous: false,
            isLocked: false,
            isActive: true,
            hasExternalPassword: false
        },
    password: "..."
};
Mistake 2: Trying to set the id or userId during creation. These fields are read-only and assigned by Kibo upon successful creation. Including them in your request payload will cause a validation error.

Multiple Real-World Examples

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

Example 1: Check if a User Exists (Get Login State)

Before showing a registration form, it’s good practice to check if an email is already in use.
import { Configuration } from "@kibocommerce/rest-sdk";
import { CustomerAccountApi } from "@kibocommerce/rest-sdk/clients/Customer";

// (Use the same 'configuration' object as defined previously)

async function checkEmailExists(email: string) {
    const customerAccountApi = new CustomerAccountApi(configuration);
    console.log(`Checking login state for: ${email}`);
    
    try {
        const loginState = await customerAccountApi.getLoginStateByEmailAddress({ emailAddress: email });
        
        console.log("Success: Login state retrieved:", loginState);
        if (loginState.isLocked) {
            console.log("Account exists but is locked.");
        } else if (loginState.createdOn) {
            console.log(`Account exists with email ID: ${email}`);
        } else {
            console.log("Account does not exist. Safe to register.");
        }
        return loginState;

    } catch (error: any) {
        // A 404 is not thrown for non-existent emails; the response body indicates existence.
        // This catch block is for other errors like authentication or malformed requests.
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// checkEmailExists("[email protected]");
// checkEmailExists("[email protected]");

Example 2: Update a Customer’s Profile

This allows a user to change their first name, last name, or marketing preferences.
import { Configuration } from "@kibocommerce/rest-sdk";
import { CustomerAccountApi} from "@kibocommerce/rest-sdk/clients/Customer"
import { CustomerAccount } from "@kibocommerce/rest-sdk/clients/Customer/models";

// (Use the same 'configuration' object as defined previously)

async function updateUserProfile(accountId: number, updatedInfo: Partial<CustomerAccount>) {
    const customerAccountApi = new CustomerAccountApi(configuration);
    console.log(`Updating profile for account ID: ${accountId}`);

    try {
        // The payload only needs the fields you want to change.
        const updatedAccount = await customerAccountApi.updateAccount({ 
            accountId: accountId,
            customerAccount: updatedInfo
        });

        console.log(`Success: Updated profile for ${updatedAccount.firstName} ${updatedAccount.lastName}.`);
        return updatedAccount;

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

// Usage: Update the user's first name and opt them out of marketing.
/*
updateUserProfile(1001, {
    firstName: "Johnny",
    acceptsMarketing: false
});
*/

Example 3: Add a New Address to an Account

This is a key part of “My Account” functionality, allowing users to build an address book.
import { Configuration } from "@kibocommerce/rest-sdk";
import { CustomerAccountApi} from "@kibocommerce/rest-sdk/clients/Customer"
import { CustomerAccount } from "@kibocommerce/rest-sdk/clients/Customer/models";

// (Use the same 'configuration' object as defined previously)

async function addAddressToAccount(accountId: number) {
    // Note: We use 'CustomerContactApi' for address operations.
    const customerAccountApi = new CustomerAccountApi(configuration);
    
    // This payload must match the CustomerContact schema.
    const newAddress: CustomerContact = {
        accountId: accountId,
        address: {
            address1: "123 Kibo Lane",
            cityOrTown: "Austin",
            stateOrProvince: "TX",
            postalOrZipCode: "78758",
            countryCode: "US",
            addressType: "Residential"
        },
        types: [{ name: "Shipping", isPrimary: true }]
    };

    console.log(`Adding new address to account ID: ${accountId}`);
    
    try {
        const addedContact = await customerAccountApi.addAccountContact({
            accountId: accountId,
            customerContact: newAddress
        });
        console.log(`Success: Added new contact with ID: ${addedContact.id}`);
        return addedContact;

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

// Usage
// addAddressToAccount(1001);

Example 4: Add a Saved Credit Card

Securely save a tokenized payment card to a customer’s account for faster checkout.
import { Configuration } from "@kibocommerce/rest-sdk";
import { CustomerAccountApi} from "@kibocommerce/rest-sdk/clients/Customer"
import { CustomerAccount } from "@kibocommerce/rest-sdk/clients/Customer/models";

// (Use the same 'configuration' object as defined previously)

// IMPORTANT: This function assumes you have already obtained a 'paymentServiceCardId' (card token)
// from your payment gateway (e.g., via a client-side SDK like Stripe.js or Braintree.js).
// NEVER send raw credit card numbers to your server or the Kibo API.
async function addSavedCard(accountId: number, cardToken: string, cardholderName: string) {
    // Note: We use the 'CustomerAccountApi' for payment card operations.
    const customerAccountApi = new CustomerAccountApi(configuration);
    
    const newCard: Card = {
        id: cardToken, // The token from the payment gateway
        isDefaultPayMethod: true,
        nameOnCard: cardholderName,
        cardType: "VISA", // Often provided by the gateway
        expireMonth: 12,
        expireYear: 2028,
        // The last 4 digits are often provided by the gateway response
        cardNumberPart: "1111" 
    };

    console.log(`Adding saved card to account ID: ${accountId}`);

    try {
        const addedCard = await customerAccountApi.addAccountCard({ 
            accountId: accountId,
            card: newCard
        });
        console.log(`Success: Added new card with ID: ${addedCard.id}`);
        return addedCard;

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

// Usage
// addSavedCard(1001, "tok_123abc456def", "Jane Doe");

Example 5: Create Account and Log In Simultaneously

This workflow is perfect for registrations that should immediately start a user session. It creates the account and returns an authentication ticket in one atomic API call.
  • API Docs: Create User Auth Ticket - Note: The SDK simplifies this into a single performCustomerAuth call. The true workflow is creating an account and then creating an auth ticket.
import { Configuration } from "@kibocommerce/rest-sdk";
import { CustomerAccountApi } from "@kibocommerce/rest-sdk/clients/Customer";
import { CustomerUserAuthInfo } from "@kibocommerce/rest-sdk/clients/Customer/models";
import { StorefrontAuthTicketApi} from "@kibocommerce/rest-sdk/clients/Customer"

// (Use the same 'configuration' object as defined previously)
async function registerAndLogin() {
    // Step 1: Create the account (reusing our function from the first section)
    const newAccount = await createNewCustomerAccount(); // Assumes 'createNewCustomerAccount' is defined
    
    if (!newAccount) {
        console.log("Account creation failed, aborting login.");
        return;
    }

    // Step 2: Authenticate to get session tickets
    const customerAuthApi = new StorefrontAuthTicketApi(configuration);
    const authPayload: CustomerUserAuthInfo = {
        username: "[email protected]",
        password: "SuperSecretPassword123!"
    };

    console.log(`Account created in step 3. Now logging in as ${authPayload.username}...`);

    try {
        const authTicket = await customerAuthApi.createUserAuthTicket({
            customerUserAuthInfo: authPayload
        });
        
        console.log("Success: Logged in and received auth ticket.");
        console.log("Access Token:", authTicket.accessToken); // This is the user's session token
        // You would typically store the accessToken and refreshToken in secure client-side storage.
        return authTicket;

    } catch (error: any) {
        console.error("Login failed after registration:", JSON.stringify(error, null, 2));
    }
}

// registerAndLogin();


Integrating Customer with Other Kibo Domains

Customer + Orders Integration

The CustomerAccount is the link to a user’s entire purchase history. When you retrieve an Order object, it will contain a customerAccountId field. You can use this ID to fetch the full customer profile. Practical Example: On an order confirmation page, you could use the customerAccountId from the order to retrieve the customer’s firstName for a personalized “Thank You, John!” message.

Customer + Carts & Checkout Integration

When a logged-in user adds items to their cart, the cart is associated with their customerAccountId. This allows for persistent carts across devices. During checkout, you can use the accountId to fetch their address book (CustomerContact objects) and saved payment methods (Card objects) to pre-fill the checkout form, drastically improving conversion rates.

Troubleshooting Your Customer Implementation

Reading Kibo Error Messages

Kibo’s error responses are structured and predictable. The SDK client will throw an error object containing a body with these key fields:
// Actual error structure from Kibo API documentation
interface KiboApiError {
  body: {
    message: string;             // Human-readable description of the error
    errorCode: string;           // A specific code for programmatic handling
    correlationId: string;       // Unique ID for this request, useful for support tickets
    items?: Array<{             // Present for validation errors
        name: string;
        errorCode: string;
        message: string;
    }>
  }
}
Common Error Codes for Customer: (from official API documentation)
  • DUPLICATE_EMAIL: Occurs when calling createAccount with an email address that already exists.
  • VALIDATION_ERROR: The request body is missing a required field or has an invalid data type. The items array in the error will specify which field failed.
  • INVALID_CREDENTIALS: Occurs during login (createUserAuthTicket) when the username or password is incorrect.
  • RESOURCE_NOT_FOUND: Trying to update or fetch a resource with an ID that doesn’t exist (e.g., updateAccount with an invalid accountId).

Common Development Issues

Issue 1: Password complexity rules causing VALIDATION_ERROR on account creation.
  • Why it happens: Every Kibo site has configurable password policies (minimum length, required characters, etc.). If the password in your createAccount payload doesn’t meet these rules, the API will reject it.
  • How to fix it: Ensure the password you send meets the site’s requirements. These are visible in the Kibo Admin under System > Settings > Password Policy.
  • How to avoid it: Implement client-side validation on your registration form that matches the Kibo password policy.
  • API Reference: Add Account (The error response will contain details in the items array).
Issue 2: Addresses or Cards not appearing after being added.
  • Why it happens: A common mistake is to add a CustomerContact or Card and then fetch the main CustomerAccount object expecting the new data to be there. The getAccount endpoint does not always return a fully hydrated object with all contacts and cards by default.
  • How to fix it: After adding a contact or card, use the specific getAccountContact or getAccountCard methods to verify it was created. Alternatively, use the getAccountContacts or getAccountCards methods to retrieve the full list.
  • API Reference: Get Account Contacts

Debugging Checklist

When your Customer implementation isn’t working:
  1. Verify Endpoint: Does the SDK method you’re calling (createAccount) correspond to the correct HTTP method and URL (POST /api/commerce/customer/accounts/) in the API docs?
  2. Confirm Request Body: console.log your payload object right before you send it. Does its structure ({ account: { ... }, password: "..." }) exactly match the schema on apidocs.kibocommerce.com?
  3. Check Authentication: Are tenantId, siteId, clientId, and sharedSecret all correctly configured? An auth error usually results in a 401 Unauthorized status.
  4. Validate IDs: If you are updating or fetching an entity (updateAccount, addAccountContact), double-check that the accountId you are using is valid and exists in the system.
  5. Review API Response: In your catch block, log the entire error object (JSON.stringify(error, null, 2)). The errorCode and message in the body will tell you exactly what went wrong.
  6. Check for Site Policies: Are there any site settings (like password policies or account lockout rules) that could be affecting your API call?