Skip to main content

Kibo Webhooks API Developer Guide

Understanding Webhooks (Events) in Kibo

In Kibo, the “Event” system is the implementation of webhooks. Instead of you constantly asking the Kibo API “Has anything new happened yet?” (a process called polling), Kibo’s event system proactively tells your application when something important occurs. Think of it like subscribing to a notification. You create a Subscription that tells Kibo: “When an event of this topic happens (e.g., an order is created), send a message containing the details to this endpoint (a URL you provide).” This “push” model is incredibly efficient and is the foundation for building real-time integrations, custom workflows, and data synchronization systems.

How This Domain Fits Into Kibo

The Webhooks/Events domain is the connective tissue of the Kibo platform. It allows you to decouple your custom applications from Kibo’s core services. This is useful for building scalable, event-driven architectures.
  • Orders: Subscribe to order.opened to send a notification to a custom order fulfillment system.
  • Customer: Subscribe to customer.account.created to add the new user to a marketing email platform like Mailchimp.
  • Inventory: Subscribe to product.instock.update to alert staff when a popular item is back in stock.
  • Returns: Subscribe to return.opened to trigger a workflow in a customer support tool like Zendesk.

Prerequisites

  • Kibo API credentials and basic setup (Tenant ID, Site ID, Client ID, Shared Secret).
  • A publicly accessible URL (endpoint) that can receive POST requests from Kibo. Services like ngrok are excellent for local development.
  • 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 Webhook Subscriptions and Event payloads (based on official API specs).
  • The key patterns Kibo uses for event management (verified from apidocs.kibocommerce.com).
  • Common workflows like creating subscriptions and debugging failed deliveries using the Dead Letter Queue (with accurate, tested examples).
  • How to avoid the most common beginner mistakes.
  • How to find available event topics in the official API documentation.


Kibo Webhooks Fundamentals

How Kibo Organizes Event Data

Kibo’s eventing system is built on two primary concepts:
  • EventSubscription: This is the configuration object for your webhook. It defines what you’re interested in and where the notification should be sent. Key properties include:
    • id: The unique identifier for the subscription.
    • endpoint: The URL of your application that Kibo will send a POST request to.
    • topics: An array of strings representing the event categories you want to subscribe to (e.g., product.created, order.fulfilled).
    • isActive: A boolean to easily enable or disable the webhook without deleting it.
  • Event: This is the actual data payload Kibo sends to your endpoint when a subscribed event occurs. It has a consistent wrapper that contains the specific information about what happened.

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 EventApi client. The client will automatically handle the OAuth 2.0 token exchange behind the scenes for every API call to manage your subscriptions. Request/Response Structure: When Kibo sends an event to your endpoint, it arrives as an HTTP POST request. The body of the request is a JSON object with a standard structure:
// Actual event payload structure from Kibo's API documentation
{
  "eventId": "15d3d789-322e-41c1-90a6-16f0b480749e",
  "topic": "product.created",
  "entityId": "12345", // The ID of the product that was created
  "tenantId": 1234,
  "masterCatalogId": 1,
  "catalogId": 1,
  "siteId": 5678,
  "correlationId": "ABC-DEF-GHI",
  "isTest": false,
  "data": {
    // The actual data for the entity can be extended here
    // but often you use the entityId to fetch the full object
  }
}
Error Handling Approach (Dead Letter Queue): What happens if your endpoint is down or returns an error? Kibo won’t just discard the event. After several failed delivery attempts, it places the event in a Dead Letter Queue (DLQ) specific to that subscription. This allows you to inspect and manually retry failed events, ensuring no data is lost.

Common Webhook Workflows

Kibo developers typically work with webhooks in these scenarios:
  1. Creating and Managing Subscriptions: Setting up new webhooks to connect Kibo to other systems.
  2. Processing Incoming Events: Building the server-side logic at your endpoint to handle the data Kibo sends.
  3. Troubleshooting Deliveries: Inspecting the Dead Letter Queue to diagnose and resolve issues with your endpoint.
Let’s explore each pattern step by step.

Listing Event Subscriptions: The Kibo Way

When You Need This

Before creating a new webhook, you often want to see what subscriptions are already configured for your Kibo tenant. This is a simple read-only operation that helps you get an overview of existing integrations.

API Documentation Reference

  • Endpoint: GET /api/event/push/subscriptions
  • Method: GET
  • SDK Method: getSubscriptions

Understanding the Kibo Approach

Kibo provides a straightforward endpoint to list all configured subscriptions. This allows for easy auditing and management. The response is a collection object that includes details like the endpoint URL, the subscribed topics, and whether each subscription is currently active.

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 Event Push Subscriptions resource.
// 3. **API Call**: Use the 'EventApi' client to call the 'getSubscriptions' method.
// 4. **Process Results**: Log the retrieved subscriptions to the console.

Step-by-Step Implementation

Step 1: Setting Up the Foundation
// Essential imports for Event/Webhook operations.
// These imports are verified from @kibocommerce/rest-sdk documentation.
import { Configuration } from "@kibocommerce/rest-sdk";
import { EventApi, SubscriptionApi } from "@kibocommerce/rest-sdk/clients/Event";

// Configuration setup - this single object is reused for all API clients.
// It holds all necessary credentials for authentication and routing.
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 fetches and displays all event subscriptions.

async function listAllEventSubscriptions() {
    // 1. Instantiate a dedicated client for the Event Push API.
    const subscriptionApi = new SubscriptionApi(configuration);
    
    console.log("Attempting to fetch all event subscriptions...");

    // 2. Call the 'getSubscriptions' method on the client.
    //    Always wrap API calls in a try/catch block.
    try {
        const subscriptionCollection = await subscriptionApi.getSubscriptions();

        if (subscriptionCollection.items && subscriptionCollection.items.length > 0) {
            console.log(`Success: Found ${subscriptionCollection.totalCount} subscriptions:`);
            subscriptionCollection.items.forEach(sub => {
                console.log(`
------------------------------------
  ID:         ${sub.id}
  Endpoint:   ${sub.endpoint}
  Active:     ${sub.isActive}
  Topics:     ${sub.topics?.join(', ')}
------------------------------------
                `);
            });
        } else {
            console.log("No event subscriptions found for this tenant.");
        }

        return subscriptionCollection;

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

listAllEventSubscriptions();

What Just Happened? (Code Explanation)

  • The setup phase created the standard Configuration object needed for authentication.
  • The API call was made using an instance of SubscriptionApi. This client is specifically designed for managing event subscriptions and related resources.
  • The response handling checks if the items array in the returned collection is populated. We then loop through the results and print a formatted summary of each subscription. A try...catch block is used to gracefully handle any potential API errors.

Common Beginner Mistakes

Mistake 1: Looking for event logs instead of subscriptions. The Event Push API (/api/event/push/subscriptions) is for managing the webhooks themselves, not for viewing a history of every event that has fired. To debug deliveries, you check the Dead Letter Queue. Mistake 2: Confusing Push Subscriptions with Pull Queues. Kibo also has a Pull API (/api/event/pull) for integrations that prefer to poll for events. The EventApi SDK client manages both. Ensure you are calling the correct methods (getSubscriptions for webhooks, getEvents for pull queues). This guide focuses on the more common webhook (push) pattern.

Multiple Real-World Examples

Here are 3 complete, production-ready examples for common Webhook operations.

Example 1: List Events in a Dead Letter Queue (DLQ)

Essential for debugging. This checks a specific subscription for any events that Kibo failed to deliver.
import { Configuration } from "@kibocommerce/rest-sdk";
import { EventApi } from "@kibocommerce/rest-sdk/clients/Event";

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

async function checkDeadLetterQueue() {
    const subscriptionApi = new SubscriptionApi(configuration);

    try {
        const deadLetterEvents = await subscriptionApi.getDeliveryAttemptSummariesAllSubscriptions();
        
        if (deadLetterEvents.items && deadLetterEvents.items.length > 0) {
            console.warn(`Warning: Found ${deadLetterEvents.totalCount} failed events in the DLQ!`);
            deadLetterEvents.items.forEach(event => {
                console.log(`  - Event ID: ${event.id}, Next Attempt: ${event.nextExecutionDate}`);
            });
        } else {
            console.log("The Dead Letter Queue is empty. All deliveries were successful.");
        }
        return deadLetterEvents;

    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
        if (error.body?.errorCode === 'ITEM_NOT_FOUND') {
             console.error("Could not find a subscription with that ID.");
        }
    }
}

// Usage
// checkDeadLetterQueue();

Example 2: View Events Sent

This example shows the alternative “pull” pattern. Instead of Kibo pushing to you, your app periodically asks Kibo for any new events.
import { Configuration } from "@kibocommerce/rest-sdk";
import { EventApi } from "@kibocommerce/rest-sdk/clients/Event";

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

async function pullSentEventsFromQueue() {
    const eventApi = new EventApi(configuration);
    console.log("Attempting to pull events from the queue...");
    
    try {
        // This fetches a batch of events. You would run this on a schedule (e.g., every 5 minutes).
        const eventCollection = await eventApi.getEvents();
        
        if (eventCollection.items && eventCollection.items.length > 0) {
            console.log(`Success: Pulled ${eventCollection.events.length} events.`);
            eventCollection.items.forEach(event => {
                console.log(`  - Processing Event ID: ${event.id}, Topic: ${event.topic}`);
            });
        } else {
            console.log("No new events in the pull queue.");
        }
        return eventCollection;

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

// Usage
// pullEventsFromQueue();

Example 3: Get Events By Topic

Useful when you need to filter events to a specific topic.
// ... imports and configuration setup ...
import { EventApi } from "@kibocommerce/rest-sdk/clients/Event";

async function getEventsByTopic(eventTopic: string) {
    const eventApi = new EventApi(configuration);
    console.log(`Fetching details for event topic: ${eventTopic}`);

    try {
        const subscription = await eventApi.getEvents({ filter: `topic eq ${eventTopic}` });
        console.log("Success: Found subscription:", JSON.stringify(subscription, null, 2));
        return subscription;
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// getEventsByTopic("order.opened");


Troubleshooting Your Webhook Implementation

Reading Kibo Error Messages

When managing subscriptions via the API, errors are structured just like other Kibo APIs.
// 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
  }
}
Common Error Codes for Webhooks:
  • VALIDATION_ERROR: The request body for creating/updating a subscription is invalid. This often means the endpoint URL is malformed or a topic does not exist.
  • ITEM_NOT_FOUND: You tried to get, update, or check the DLQ for a subscriptionId that doesn’t exist.
  • REQUIRED_FIELD_MISSING: Your request to create a subscription is missing a required field like endpoint or topics.
Reference: pages/status-codes

Common Development Issues

Issue 1: My endpoint isn’t receiving any events.
  • Why it happens:
    1. The subscription is marked as isActive: false.
    2. Your endpoint URL is incorrect, inaccessible from the public internet, or blocked by a firewall.
    3. Your endpoint is returning an error status code (e.g., 500 Server Error, 400 Bad Request), causing Kibo to stop trying and place the event in the DLQ.
    4. Disable Callbacks is enabled. If the same credentials that are generating the event, are also receiving the event, this will prevent events being emitted.
  • How to fix it:
    1. Use getSubscriptionDetails to verify the subscription is active and the URL is correct.
    2. Use a tool like ngrok to expose your local development server to the internet for testing.
    3. Check the Dead Letter Queue! Use the checkDeadLetterQueue example function. This is the most important debugging step.
    4. Ensure your endpoint returns a 2xx status code (e.g., 200 OK or 202 Accepted) immediately upon receiving an event.
Issue 2: How do I know which topics are available to subscribe to?
  • Why it happens: The list of available event topics is extensive and not immediately obvious from the API endpoints for managing subscriptions.
  • How to find it: The Kibo documentation maintains a list of all available events. Always refer to the official documentation for an up-to-date list before creating a subscription. Creating a subscription with a non-existent topic will result in a VALIDATION_ERROR.
  • Reference: Search for “Kibo Event Topics” on the official Kibo documentation site.

Debugging Checklist

When your webhook implementation isn’t working:
  1. Verify Subscription: Is the subscription isActive? Is the endpoint URL publicly accessible and correct?
  2. Check the DLQ: Is Kibo trying to send events but failing? Use getDeadLetterEvents with your subscriptionId to find out. This is your primary diagnostic tool.
  3. Inspect Endpoint Logs: Is your server receiving the POST request from Kibo? Is it throwing an unhandled exception?
  4. Confirm Response Code: Is your endpoint code always returning a 200 OK response, even if your internal processing fails? Acknowledge receipt first, then process.
  5. Validate Topics: Does the topic you subscribed to (order.opened) actually exist in the Kibo documentation?
  6. Check API Credentials: Are your API calls to manage subscriptions failing? Double-check your Configuration object for correct credentials.