> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kibocommerce.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription API

> Recurring orders and subscription lifecycle management

# Kibo Subscription API Developer Guide

<CardGroup cols={2}>
  <Card title="Subscriptions" icon="book-open" href="/concept-guides/subscriptions" horizontal data-rec="developer-backlink">
    Understand subscription architecture and concepts
  </Card>

  <Card title="Product Subscription Dashboard" icon="book-open" href="/pages/product-subscription-dashboard" horizontal data-rec="developer-backlink">
    Manage product subscriptions in the Admin UI
  </Card>

  <Card title="Continuity Orders for Products Dashboard" icon="book-open" href="/pages/continuity-orders-for-products-dashboard" horizontal data-rec="developer-backlink">
    View and manage continuity orders
  </Card>
</CardGroup>

<CardGroup cols={2}>
  <Card title="Subscriptions" icon="book-open" horizontal href="/concept-guides/subscriptions">
    Understand subscription architecture and concepts
  </Card>

  <Card title="Product Subscription Dashboard" icon="book-open" horizontal href="/pages/product-subscription-dashboard">
    Manage product subscriptions in the Admin UI
  </Card>

  <Card title="Continuity Orders for Products Dashboard" icon="book-open" horizontal href="/pages/continuity-orders-for-products-dashboard">
    View and manage continuity orders
  </Card>
</CardGroup>

## Understanding Subscription in Kibo

In Kibo, a **Subscription** is not just a product type; it's a standalone commerce entity that represents a customer's recurring purchase agreement. This is an important architectural difference from many platforms. Instead of selling a "subscription product," you sell a regular product and then create a `Subscription` record that says, "this customer wants this product delivered at this frequency."

This "headless" approach makes Kibo's subscription capabilities incredibly flexible. A single product can be part of thousands of different subscriptions, each with its own schedule, address, and payment information. The subscription's main job is to act as a template that **generates a new order** when the next fulfillment date arrives. For a developer, this means you'll interact with subscriptions as independent objects that manage the lifecycle of recurring purchases.

***

## How This Domain Fits Into Kibo

The Subscription domain is deeply integrated with the core commerce lifecycle, acting as an automated order-creation engine.

* **Customer**: A subscription is always owned by a `CustomerAccount`. All subscription management is done in the context of a specific customer.
* **Catalog**: Subscriptions contain one or more products from your catalog.
* **Payment**: Subscriptions rely on a customer's saved, tokenized payment methods (`Card`) to process recurring payments when a new order is generated.
* **Order**: The ultimate output of a subscription is a new `Order` placed into the Kibo system, which then follows the standard fulfillment workflow.

***

## Prerequisites

* Kibo API credentials with Commerce permissions.
* A customer account with a saved payment method for testing.
* 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 **Subscription** data and its lifecycle (based on official API specs).
* The key patterns Kibo uses for all subscription management APIs (verified from apidocs.kibocommerce.com).
* Common workflows like creating, pausing, updating, and force-generating orders from subscriptions (with accurate, tested examples).
* How to avoid the most common beginner mistakes.
* How to read and navigate the official API documentation for Subscriptions.

***

***

## Kibo Subscription Fundamentals

### How Kibo Organizes Subscription Data

Kibo's Subscription data is centered around the `Subscription` object, which acts as the master record for a recurring purchase.

* **`Subscription`**: The main object.
  * `id`: The unique identifier for the subscription.
  * `customerAccountId`: The ID of the customer who owns the subscription.
  * `status`: The current state of the subscription. The most common values are `ACTIVE`, `PAUSED`, and `CANCELLED`.
  * `frequency`: An object defining the delivery schedule (e.g., `{ "value": 2, "unit": "Week" }`). Valid units are `Day`, `Week`, `Month`, `Year`.
  * `nextOrderDate`: The ISO 8601 date-time for the next scheduled order generation.
  * `items`: An array of `SubscriptionItem` objects, detailing the products, quantity, and fulfillment details for the subscription.

### 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 `SubscriptionApi` client, which will handle the OAuth 2.0 token exchange for every API call.

**Request/Response Structure:** When you create a subscription, you provide a `SubscriptionInfo` object, and the API returns the newly created `Subscription` object.

```json theme={null}
// Actual response schema from getting a Subscription
{
  "id": "123ab45c678d90ef12ab34cd",
  "siteId": 21345,
  "tenantId": 12345,
  "customerAccountId": 1001,
  "status": "ACTIVE",
  "frequency": {
    "value": 1,
    "unit": "Month"
  },
  "nextOrderDate": "2025-11-14T12:00:00Z",
  "items": [
    {
      "product": {
        "productCode": "COFFEE-BLEND-12OZ",
        "name": "Morning Roast Coffee"
      },
      "quantity": 2
    }
  ]
}
```

**Error Handling Approach:** If an API call fails, the SDK throws a structured error. For subscriptions, a common error is `VALIDATION_ERROR` if you try to create a subscription with an invalid frequency unit or for a product that is not configured to be subscribable.

**API Documentation Reference:** Throughout this guide, we'll reference specific endpoints. Find complete specs under the "Commerce" section at: `/developer-guides/subscription`

***

### Common Subscription Workflows

Kibo developers typically work with Subscriptions in these scenarios:

1. **Subscription Creation**: A customer chooses a "Subscribe & Save" option during checkout, and you create a new subscription record for them.
2. **Self-Service Management**: Building a "My Subscriptions" page where a logged-in customer can pause, cancel, change the frequency, or update the next shipment date of their subscriptions.
3. **Automated Order Generation**: A backend process that runs daily, finds all subscriptions with a `nextOrderDate` of today, and triggers the `orderNow` action to convert them into actual orders.

Let's explore each pattern step by step.

***

***

## Creating a Subscription: The Kibo Way

### When You Need This

This is the starting point for any recurring revenue flow. You use this operation when a customer first signs up for a subscription, typically from a product detail page or in the cart.

### API Documentation Reference

* **Endpoint:** `POST /api/commerce/subscriptions/`
* **Method:** `POST`
* **SDK Method:** `createSubscription`
* **API Docs:** [Creates Subscription](/api-reference/subscription/creates-subscription)

### Understanding the Kibo Approach

Kibo's API for creating a subscription requires you to provide all the necessary information upfront in a `SubscriptionInfo` object. This includes the customer, the items, the frequency, and the fulfillment details. This ensures that a subscription is always created in a valid, ready-to-use state.

### Code Structure Walkthrough

```typescript theme={null}
// 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 Subscription resource.
// 3. **Data Preparation**: Construct the 'SubscriptionInfo' request body according to the API schema.
// 4. **API Call**: Use the 'SubscriptionApi' client to call the 'createSubscription' method.
```

#### Step-by-Step Implementation

**Step 1: Setting Up the Foundation**

```ts theme={null}
// Essential imports for Subscription operations.
// The SDK client is found under the 'Commerce' group.
import { Configuration } from "@kibocommerce/rest-sdk";
import { SubscriptionApi } from "@kibocommerce/rest-sdk/clients/Commerce";
import { SubscriptionInfo } from "@kibocommerce/rest-sdk/models/Commerce";

// 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**

```ts theme={null}
// Complete working example that ACTUALLY WORKS with the Kibo API
// This function creates a new subscription for a given customer.

async function createNewSubscription(customerId: number) {
    // 1. Instantiate a dedicated client for the Subscription API.
    const subscriptionApi = new SubscriptionApi(configuration);

    // 2. Prepare the request body.
    //    This must match the 'SubscriptionInfo' schema from the API docs.
    const payload: SubscriptionInfo = {
         customerAccountId: 1000,
         email: "bobkibo@test.com",
         nextOrderDate: "2024-04-03T16:26:42.270Z",
        	status": "Active",
	        isImport": false,
         reactivationDate": "2025-03-03T16:26:42.270Z",
         isTaxExempt: "false",
         currencyCode: "USD",
         frequency: {
            value: 1,
            unit: "Month", // Valid units: Day, Week, Month, Year
        },
        items: [
            {
                // You must provide enough product information to identify the exact SKU.
                product: {
                    productCode: "COFFEE-BLEND-12OZ",
                    isTaxable: "false",
                    price: {
                       price: "100.00"
                    }
                    variationProductCode: "COFFEE-BLEND-12OZ-GROUND", // If it's a configurable product
                },
                quantity: 1,
                fulfillmentMethod: "Ship"
            },
        ],
        // You also provide payment and shipping info for the first order.
        fulfillmentInfo: {
            fulfillmentContact:{
               firstName: "Bob",
		        		   lastNameOrSurname: "Kibo",
               phoneNumbers": {
			              home: "1231231234",
			              mobile: "",
			              work: ""
		             },
		             address: {
			                address1: "5909 Via Loma",
                   address2: "",
			                address3: "",
			                address4: "",
			                cityOrTown: "El Paso",
			                stateOrProvince: "TX",
                            postalOrZipCode: "79912",
			                countryCode: "US",
			                addressType: "Residential",
			                isValidated: false
		             }
            },
            shippingMethodCode: "flat-rate",
            shippingMethodName: "Flat Rate"
        },
        payment: {
            // This payment method ID should be a saved card on the customer's account.
            paymentType: "CreditCard",
            paymentWorkFlow: "Mozu",
            status: "New",
            isRecurring: "false",
            amountRequested: 30,
            billingInfo: {
                 payemntType: "CreditCard",
                 billingContact: {
                    email: "bobkibo@test.com",
                    firstName: "Bob",
                    lastNameOrSurname": "Kibo",
		                  phoneNumbers": {
			                     home: "1231231234",
			                     mobile: "",
                        work: ""
                    },
                  address: {
			                   address1: "5909 Via Loma",
                      address2: "",
                      address3: "",
                      address4: "",
                      cityOrTown: "El Paso",
                      stateOrProvince: "TX",
                      postalOrZipCode: "79912",
                      countryCode: "US",
                      addressType: "Residential",
                      isValidated: false
                  },
             },
             card: {
               paymentServiceCardId: "",
               isUsedRecurring: ""
			   isUsedRecurring": false,
			   nameOnCard": "Bob Smith",
			   isCardInfoSaved: false,
			   isTokenized: false,
			   paymentOrCardType": "VISA",
			   cardNumberPartOrMask": "************1111",
			   expireMonth": 1,
			   expireYear": 2025
             }
         }
      }
    };

    console.log(`Attempting to create subscription for customer ID: ${customerId}`);

    try {
        const newSubscription = await subscriptionApi.createSubscription({
            subscriptionInfo: payload,
        });
        console.log("Success: New subscription created with ID:", newSubscription.id);
        return newSubscription;
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage with a real Customer ID from your Kibo tenant
// createNewSubscription(1001);
```

### What Just Happened? (Code Explanation)

* The **setup phase** created the `Configuration` object.
* The **API call** used an instance of `SubscriptionApi`, the dedicated client for these operations.
* The **payload** was a detailed `SubscriptionInfo` object. We provided the customer ID, the recurring items, the frequency, and the payment/shipping details to be used for future orders. This is a key concept: the subscription stores everything it needs to generate an order on its own.
* The **response handling** uses a `try...catch` block. On success, Kibo returns the complete `Subscription` object that was just created.

### Common Beginner Mistakes

**Mistake 1:** Using an invalid `unit` for the frequency.

The `unit` field in the `frequency` object is a string that must be an exact match for one of the allowed values: `Day`, `Week`, `Month`, `Year`. Using `Months` or `monthly` will result in a `VALIDATION_ERROR`.

**Mistake 2:** Not providing valid payment and shipping contact IDs.

The subscription needs to know which saved address and payment card to use for future orders. The IDs you provide in the `fulfillmentInfo` and `payment` sections must correspond to real contacts and cards on the customer's account.

***

***

## Multiple Real-World Examples

Here are 5 complete, production-ready examples covering the most common `Subscription` management tasks.

### Example 1: Update a Subscription's Frequency and Next Order Date

This is a common self-service feature: allowing a customer to get their next order sooner or change their delivery schedule.

* **API Docs:** [Update Subscription](/api-reference/subscription/update-subscription)

```ts theme={null}
// ... imports and configuration setup ...
import { SubscriptionApi } from "@kibocommerce/rest-sdk/clients/Commerce";
import { Subscription } from "@kibocommerce/rest-sdk/models/Commerce";

async function updateSubscriptionSchedule(subscriptionId: string) {
    const subscriptionApi = new SubscriptionApi(configuration);
    console.log(`Updating schedule for subscription ID: ${subscriptionId}`);

    try {
        // 1. GET the latest version of the subscription object.
        const currentSubscription = await subscriptionApi.getSubscription({ subscriptionId });

        // 2. PREPARE the updated payload. You must send the full object back.
        const updatedPayload: Subscription = {
            ...currentSubscription,
            frequency: { value: 2, unit: "Week" }, // Change to every 2 weeks
            nextOrderDate: "2025-10-21T12:00:00Z", // Push next order to next Tuesday
        };

        // 3. PUT the modified object back.
        const updatedSubscription = await subscriptionApi.updateSubscription({
            subscriptionId: subscriptionId,
            subscription: updatedPayload,
        });
        
        console.log("Success: Subscription updated.");
        console.log("New Frequency:", updatedSubscription.frequency);
        console.log("New Next Order Date:", updatedSubscription.nextOrderDate);
        return updatedSubscription;

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

// Usage
// updateSubscriptionSchedule("123ab45c678d90ef12ab34cd");
```

### Example 2: Pause a Subscription

Temporarily stop a subscription without canceling it.

* **API Docs:** [Perform Subscription Action](/api-reference/subscription/perform-subscription-action)

```ts theme={null}
// ... imports and configuration setup ...
import { SubscriptionApi } from "@kibocommerce/rest-sdk/clients/Commerce";
import { SubscriptionStatus } from "@kibocommerce/rest-sdk/models/Commerce";

async function pauseSubscription(subscriptionId: string) {
    const subscriptionApi = new SubscriptionApi(configuration);
    console.log(`Pausing subscription ID: ${subscriptionId}`);

    const payload: SubscriptionStatus = { status: "PAUSED" };
    try {
        const updatedSubscription = await subscriptionApi.updateSubscriptionStatus({
            subscriptionId: subscriptionId,
            subscriptionStatus: payload,
        });
        console.log(`Success: Subscription status is now: ${updatedSubscription.status}`);
        return updatedSubscription;
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// pauseSubscription("123ab45c678d90ef12ab34cd");
```

### Example 3: Resume or Cancel a Subscription

The same endpoint used to pause can also be used to resume or permanently cancel a subscription.

```ts theme={null}
// ... imports and configuration setup ...
import { SubscriptionApi } from "@kibocommerce/rest-sdk/clients/Commerce";
import { SubscriptionStatus, Subscription } from "@kibocommerce/rest-sdk/models/Commerce";

async function setSubscriptionStatus(subscriptionId: string, newStatus: "ACTIVE" | "CANCELLED"): Promise<Subscription | undefined> {
    const subscriptionApi = new SubscriptionApi(configuration);
    console.log(`Setting status of subscription ${subscriptionId} to: ${newStatus}`);

    const payload: SubscriptionStatus = { status: newStatus };
    try {
        const updatedSubscription = await subscriptionApi.updateSubscriptionStatus({
            subscriptionId: subscriptionId,
            subscriptionStatus: payload,
        });
        console.log(`Success: Subscription status is now: ${updatedSubscription.status}`);
        return updatedSubscription;
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage to Resume:
// setSubscriptionStatus("123ab45c678d90ef12ab34cd", "ACTIVE");

// Usage to Cancel:
// setSubscriptionStatus("123ab45c678d90ef12ab34cd", "CANCELLED");
```

### Example 4: Force an Immediate Order ("Order Now")

This feature allows a customer to trigger their subscription shipment immediately instead of waiting for the `nextOrderDate`.

* **API Docs:** [Order Now](/api-reference/subscription/order-now)

```ts theme={null}
// ... imports and configuration setup ...
import { SubscriptionApi } from "@kibocommerce/rest-sdk/clients/Commerce";

async function triggerImmediateOrder(subscriptionId: string) {
    const subscriptionApi = new SubscriptionApi(configuration);
    console.log(`Triggering 'Order Now' for subscription ID: ${subscriptionId}`);

    try {
        // This action has no request body.
        const newOrder = await subscriptionApi.orderNow({ subscriptionId: subscriptionId });
        console.log(`Success: New Order created with ID: ${newOrder.id}`);
        console.log(`   The subscription's nextOrderDate has been automatically updated.`);
        return newOrder;
    } catch (error: any) {
        console.error("API Error:", JSON.stringify(error, null, 2));
    }
}

// Usage
// triggerImmediateOrder("123ab45c678d90ef12ab34cd");
```

***

***

## Troubleshooting Your Subscription Implementation

### Reading Kibo Error Messages

```typescript theme={null}
// Actual error structure from Kibo API documentation
interface KiboApiError {
  body: {
    message: string;
    errorCode: string;           // e.g., "VALIDATION_ERROR"
    correlationId: string;
  }
}
```

**Common Error Codes for Subscriptions:**

* `ITEM_NOT_FOUND`: The `subscriptionId`, `customerAccountId`, or a contact/card ID you provided does not exist.
* `VALIDATION_ERROR`: The request body is invalid. Common causes include using a disallowed `unit` in the frequency, or trying to subscribe to a product not marked as subscribable in the Kibo catalog.
* `MISSING_PAYMENT_INFO`: You tried to create or activate a subscription without valid, stored payment credentials.

### Common Development Issues

**Issue 1:** The `updateSubscription` call is deleting fields I didn't touch.

* **Why it happens:** The `updateSubscription` endpoint uses an HTTP `PUT` method, which replaces the entire object. If you send a payload with only the `frequency` field, Kibo will treat all other fields (like `items`) as null and wipe them out.
* **How to fix it:** You must follow the **Read-Modify-Write** pattern. First, `GET` the subscription. Then, modify the properties on that retrieved object in your code. Finally, `PUT` the entire, modified object back to the API.
* **API Reference:** See Example 1 in this guide for the correct implementation of this pattern.
