---
title: "Import Knowledge Base Categories"
url: "https://help.productfruits.com/en/article/knowledge-base-api-import-categories"
language: "en"
last_updated: "2025-12-22T12:34:14.509Z"
---

# Import Knowledge Base Categories

## POST /categories/import - Import Knowledge Base Categories

Import or update knowledge base categories with multilingual content. This endpoint allows you to create new categories, update existing ones, and manage category hierarchies with parent-child relationships.

## Endpoint

```
POST /v1/knowledgebase/categories/import
```

## Request Headers

| Header | Value | Required |
| --- | --- | --- |
| `Authorization` | `Bearer YOUR_API_TOKEN` | Yes |
| `Content-Type` | `application/json` | Yes |

## Request Body

### CategoryImportRequest

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `categories` | `array` | Yes | Array of categories to import (empty array deletes all categories) |
| `config` | `object` | No | Import configuration options |

### CategoryImportItem (`categories[]`)

| Field | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `id` | `number` | Yes | Category ID: negative for new (-1, -2), positive for existing (1, 2) | `-1` |
| `correlationId` | `string` | No | Custom identifier for external system sync | `"docs-category"` |
| `parentCategoryId` | `number` | No | Parent category ID (null for root categories) | `null` |
| `order` | `number` | No | Display order within parent category | `1` |
| `isFeatured` | `boolean` | No | Whether category is featured | `false` |
| `icon` | `string` | No | Category icon (CDN image GUID) | `"image-guid-123"` |
| `contents` | `array` | Yes | Category content in different languages |  |

### CategoryContentImportItem (`contents[]`)

| Field | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `lang` | `string` | Yes | Language code (ISO 639-1) | `"en"` |
| `title` | `string` | Yes | Category title | `"Documentation"` |
| `description` | `string` | No | Category description | `"All documentation articles"` |
| `slug` | `string` | No | URL slug (required if slug\_state is "manual") | `"docs"` |
| `slug_state` | `string` | No | Slug generation mode: "auto" or "manual" (default: "auto") | `"manual"` |

### CategoryImportConfig (`config`)

| Field | Type | Required | Description | Default |
| --- | --- | --- | --- | --- |
| `slugConflictHandling` | `string` | No | Handle slug conflicts: "error" or "auto-number" | `"error"` |
| `articleHandling` | `string` | No | Reserved for future use (currently import fails if deleted categories contain articles) | `"error"` |

## Example Request

### JSON Request

```json
{
  "categories": [
    {
      "id": -1,
      "correlationId": "docs-category",
      "parentCategoryId": null,
      "order": 1,
      "isFeatured": false,
      "icon": "image-guid-123",
      "contents": [
        {
          "lang": "en",
          "title": "Documentation",
          "description": "All documentation articles",
          "slug": "docs",
          "slug_state": "manual"
        }
      ]
    }
  ],
  "config": {
    "slugConflictHandling": "error"
  }
}
```

## Success Response (200 OK)

```json
{
  "categories": [
    {
      "id": 123,
      "correlationId": "docs-category",
      "parentCategoryId": null,
      "order": 1,
      "isFeatured": false,
      "icon": "image-guid-123",
      "status": "created",
      "contents": [
        {
          "lang": "en",
          "title": "Documentation",
          "description": "All documentation articles",
          "slug": "docs",
          "slug_state": "manual",
          "status": "created"
        }
      ]
    }
  ],
  "errors": []
}
```

## Status Values

### Category Status Values

-   `created`: New category was created
-   `updated`: Existing category was updated
-   `error`: Category processing failed

### Content Status Values

-   `created`: New content was created
-   `updated`: Existing content was updated
-   `error`: Content processing failed

## Correlation IDs

Correlation IDs allow you to sync your external system IDs with our internal database IDs. We store your correlation IDs and use them to find and match categories for updates.

**Category Correlation ID**: Your external identifier for categories (e.g., from your CMS, documentation system, or database)

**ID Format Options:**

-   **Your External IDs**: Use any string identifier from your system (e.g., `"docs-category"`, `"help-section-v2"`, `"cms-cat-123"`)
-   **Internal Database IDs**: Use our internal numeric IDs prefixed with `"pf_"` (e.g., `"pf_456"` for internal ID 456)

**Example Workflow:**

-   Import category with `correlationId: "your-docs-category"`
-   We store this correlation and return our internal `categoryId: 123`
-   Later, update the same category using either:
-   Your correlation ID: `"your-docs-category"`
-   Our internal ID: `"pf_123"`
-   When importing articles, reference this category using the same correlation ID: `"your-docs-category"`

**Cross-System Integration:**

-   Categories created with correlation IDs can be referenced in article imports
-   Articles can specify `correlationCategoryId: "your-docs-category"` to assign them to the correct category
-   This enables seamless synchronization between your external system and our knowledge base

## Category ID Logic

### ⚠️ **IMPORTANT: Full Replacement Behavior**

This endpoint performs **full replacement** of your category structure:

-   **Categories in request**: Created (if new) or updated (if existing)
-   **Categories not in request**: Deleted from your knowledge base
-   **Empty array**: Deletes ALL existing categories
-   **Hierarchy preserved**: Parent-child relationships maintained during import

To safely update categories:

-   **Load existing categories** using `GET /categories`
-   **Modify/extend** the data as needed
-   **Pass the complete set** to this import endpoint

**Never send partial category lists** unless you want to delete the missing ones!

### Alternative: Single Category Operations

If you need to work with individual categories without affecting the entire structure, use these dedicated endpoints:

-   **Get single category**: [GET /categories/{correlationId}](https://help.productfruits.com/en/article/knowledge-base-api-get-specific-category)
-   **Update single category**: [PUT /categories/{correlationId}](https://help.productfruits.com/en/article/knowledge-base-api-update-specific-category)
-   **Delete single category**: [DELETE /categories/{correlationId}](https://help.productfruits.com/en/article/knowledge-base-api-delete-category)

These endpoints allow precise control without the risk of accidentally affecting other categories.

### Creating New Categories

Use **negative IDs** (-1, -2, -3, etc.) to create new categories:

-   Each negative ID represents a new category to be created
-   The system assigns actual positive IDs after creation
-   Use negative IDs to reference parent-child relationships within the same request

### Updating Existing Categories

Use **positive IDs** (1, 2, 3, etc.) to update existing categories:

-   Must match existing category IDs in your knowledge base
-   Only provided fields will be updated (partial updates supported)
-   **⚠️ Categories not included in request will be DELETED**

### Parent-Child Relationships

-   `parentCategoryId: null` creates root-level categories
-   `parentCategoryId: -1` references the category with `id: -1` in the same request
-   `parentCategoryId: 123` references existing category with ID 123

## Slug Management

### Automatic Slug Generation (`slug_state: "auto"`)

-   System generates slug from category title **only when no slug is provided**
-   **Important**: Existing slugs are NOT automatically updated when title changes
-   Default behavior when `slug_state` is omitted
-   To update an auto slug: omit the `slug` field and the system will regenerate from the new title

### Manual Slug Control (`slug_state: "manual"`)

-   You provide the exact slug to use
-   Slug field is required when using manual mode
-   Slug remains unchanged unless explicitly updated

### Slug Conflict Handling

Configure via `config.slugConflictHandling`:

-   `"error"` (default): Import fails if slug already exists
-   `"auto-number"`: Automatically appends numbers (e.g., "docs", "docs2", "docs3")

### Slug Update Behavior

**Key Point**: The system only generates/regenerates slugs when the `slug` field is empty or omitted:

-   **Creating new content**: If `slug` is omitted and `slug_state` is "auto", slug is generated from title
-   **Updating existing content**:
-   If you provide a `slug` value → uses that exact slug
-   If you omit the `slug` field and `slug_state` is "auto" → regenerates slug from title
-   If you omit the `slug` field and `slug_state` is "manual" → throws validation error

## Best Practices

-   **⚠️ Load-Modify-Import Workflow**: Always load existing categories with `GET /categories`, modify the data, then import the complete set
-   **Use Correlation IDs**: Always provide correlation IDs for categories - essential for updates and article-category linking
-   **Plan Category Structure**: Design your hierarchy before importing to avoid complex parent-child references
-   **Cross-System Sync**: Use consistent correlation IDs across category and article imports for seamless integration
-   **Test First**: Use the test environment to validate your import payload before production

### Recommended Workflow

```bash
# 1. Load existing categories
curl -X GET "https://api.productfruits.com/v1/knowledgebase/categories" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

# 2. Modify/extend the returned data as needed
# 3. Add new categories with negative IDs
# 4. Import complete set
curl -X POST "https://api.productfruits.com/v1/knowledgebase/categories/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categories": [
      // Include ALL existing categories (modified as needed)
      // Plus any new categories with negative IDs
      // Exclude ones to be removed
    ]
  }'
```

## Common Error Scenarios

### HTTP Error Codes

-   `400 Bad Request`: Invalid request format, missing required fields, or validation errors
-   `401 Unauthorized`: Invalid or missing API token
-   `403 Forbidden`: Insufficient permissions
-   `429 Too Many Requests`: Rate limit exceeded
-   `500 Internal Server Error`: Server-side processing error

### Processing Errors (in `errors[]` array)

-   Invalid category ID references
-   Slug conflicts when using "error" handling
-   Missing required content fields
-   Invalid language codes
-   Categories with articles cannot be deleted

### ⚠️ **Accidental Data Loss**

**Most Common Mistake**: Sending partial category lists and accidentally deleting existing categories  
**Prevention**: Always use the Load-Modify-Import workflow described in Best Practices

## Common Error Scenarios

-   **Missing Required Fields**: Ensure `id` and `contents` with at least one language are provided for all categories
-   **Invalid Category IDs**: Use positive numbers for existing categories, negative numbers for new categories (never 0)
-   **Duplicate IDs**: Each category ID must be unique within the request
-   **Parent Reference Errors**: Verify parent category IDs exist in the request or database
-   **Circular Dependencies**: Ensure parent-child relationships don't create circular references
-   **Language Validation**: Use valid ISO 639-1 language codes (e.g., 'en', 'es', 'fr')
-   **Slug Conflicts**: Handle slug conflicts with appropriate `slugConflictHandling` configuration
-   **Categories with Articles**: Categories containing articles cannot be deleted without `articleHandling` configuration

### Error Response (400 Bad Request)

The API returns different types of errors depending on what went wrong:

-   **HTTP 400**: Validation errors, malformed requests, or business logic violations
-   **HTTP 401**: Authentication failures or invalid API tokens
-   **HTTP 500**: Internal server errors during processing

Error messages include array indices (e.g., `Category[0]`, `Category[1].Contents[0]`) to help you identify exactly which item in your request caused the issue.

#### Validation Errors

```json
{
  "errors": [
    "Category[0]: 'id' is required. Use positive numbers for existing categories or negative numbers for new categories",
    "Category[1]: ID cannot be 0. Use positive numbers for existing categories or negative numbers for new categories",
    "Category[2]: Duplicate ID '-1' found in request",
    "Category[3]: Parent category with ID '-999' not found in request",
    "Category[4]: 'contents' is required and must contain at least one language",
    "Category[5].Contents[0]: Language code is required",
    "Category[6].Contents[1]: Invalid language code 'invalid'. Use ISO 639-1 codes like 'en', 'es', 'fr'",
    "Category[7].Contents[0]: Title is required for language 'en'",
    "Category[8]: Circular dependency detected in parent-child relationships"
  ]
}
```

#### Business Logic Errors

```json
{
  "errors": [
    "Category with ID 999 not found",
    "Cannot delete category that contains articles",
    "Slug 'docs' for language 'en' is already in use. Use slugConflictHandling: 'auto-number' to automatically resolve conflicts",
    "Invalid config.slugConflictHandling value 'invalid'. Supported values: 'error', 'auto-number'"
  ]
}
```

## Examples

### Example 1: Create New Categories with Hierarchy

```bash
curl -X POST "https://api.productfruits.com/v1/knowledgebase/categories/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categories": [
      {
        "id": -1,
        "correlationId": "docs-category",
        "parentCategoryId": null,
        "order": 1,
        "isFeatured": true,
        "icon": "image-guid-123",
        "contents": [
          {
            "lang": "en",
            "title": "Documentation",
            "description": "All documentation and guides",
            "slug": "docs",
            "slug_state": "manual"
          }
        ]
      },
      {
        "id": -2,
        "correlationId": "getting-started",
        "parentCategoryId": -1,
        "order": 1,
        "contents": [
          {
            "lang": "en",
            "title": "Getting Started",
            "description": "Beginner guides and tutorials",
            "slug_state": "auto"
          }
        ]
      }
    ],
    "config": {
      "slugConflictHandling": "auto-number"
    }
  }'
```

**Response:**

```json
{
  "categories": [
    {
      "id": 123,
      "correlationId": "docs-category",
      "parentCategoryId": null,
      "order": 1,
      "isFeatured": true,
      "icon": "image-guid-123",
      "status": "created",
      "contents": [
        {
          "lang": "en",
          "title": "Documentation",
          "description": "All documentation and guides",
          "slug": "docs",
          "slug_state": "manual",
          "status": "created"
        }
      ]
    },
    {
      "id": 124,
      "correlationId": "getting-started",
      "parentCategoryId": 123,
      "order": 1,
      "isFeatured": false,
      "icon": null,
      "status": "created",
      "contents": [
        {
          "lang": "en",
          "title": "Getting Started",
          "description": "Beginner guides and tutorials",
          "slug": "getting-started",
          "slug_state": "auto",
          "status": "created"
        }
      ]
    }
  ],
  "errors": []
}
```

### Example 2: Update Existing Category

```bash
curl -X POST "https://api.productfruits.com/v1/knowledgebase/categories/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categories": [
      {
        "id": 123,
        "correlationId": "docs-category",
        "isFeatured": false,
        "contents": [
          {
            "lang": "en",
            "title": "Documentation Hub",
            "description": "Updated description for documentation"
          }
        ]
      }
    ]
  }'
```

### Example 3: Clear All Categories

```bash
curl -X POST "https://api.productfruits.com/v1/knowledgebase/categories/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categories": []
  }'
```

**Response:**

```json
{
  "categories": [],
  "errors": []
}
```

**Article Handling**:

-   **By default**: Import fails with error if categories contain articles
-   **With** **`articleHandling: "move-to-root"`**: Categories can be removed and articles are moved to root level (no category assignment)

**Example with article handling:**

```bash
curl -X POST "https://api.productfruits.com/v1/knowledgebase/categories/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categories": [],
    "config": {
      "articleHandling": "move-to-root"
    }
  }'
```

### Example 4: Error Handling Example

```bash
curl -X POST "https://api.productfruits.com/knowledgebase/v1/categories/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categories": [
      {
        "id": -1,
        "contents": [
          {
            "lang": "en",
            "slug": "docs",
            "slug_state": "manual"
          }
        ]
      }
    ]
  }'
```

**Response (400 Bad Request):**

```json
{
  "errors": [
    "Category[0]: Title is required for language 'en'"
  ]
}
```

## Additional Examples

### Example 1: Hierarchical Categories with Multiple Languages

```bash
curl -X POST "https://api.productfruits.com/v1/knowledgebase/categories/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categories": [
      {
        "id": -1,
        "correlationId": "parent-docs",
        "parentCategoryId": null,
        "order": 1,
        "isFeatured": true,
        "icon": "image-guid-123",
        "contents": [
          {
            "lang": "en",
            "title": "Documentation",
            "description": "All documentation articles",
            "slug": "docs",
            "slug_state": "manual"
          },
          {
            "lang": "es",
            "title": "Documentación",
            "description": "Todos los artículos de documentación",
            "slug": "docs-es",
            "slug_state": "manual"
          }
        ]
      },
      {
        "id": -2,
        "correlationId": "child-getting-started",
        "parentCategoryId": -1,
        "order": 1,
        "isFeatured": false,
        "icon": "image-guid-456",
        "contents": [
          {
            "lang": "en",
            "title": "Getting Started",
            "description": "Quick start guides",
            "slug_state": "auto"
          },
          {
            "lang": "es",
            "title": "Comenzando",
            "description": "Guías de inicio rápido",
            "slug_state": "auto"
          }
        ]
      }
    ],
    "config": {
      "slugConflictHandling": "auto-number"
    }
  }'
```

### Example 2: Update Existing Category

```bash
curl -X POST "https://api.productfruits.com/v1/knowledgebase/categories/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categories": [
      {
        "id": 123,
        "correlationId": "existing-category",
        "isFeatured": true,
        "contents": [
          {
            "lang": "en",
            "title": "Updated Documentation",
            "description": "Updated description"
          }
        ]
      }
    ]
  }'
```

## Rate Limiting

Please consult this [guide](https://https//help.productfruits.com/en/article/rest-api-rate-limiting) for detailed information about API limits and optimization strategies.
