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/knowledge-base/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

{
  "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)

{
  "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:

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
# 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

{
  "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

{
  "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

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:

{
  "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

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

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:

{
  "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:

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

curl -X POST "https://api.productfruits.com/knowledge-base/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):

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

Additional Examples

Example 1: Hierarchical Categories with Multiple Languages

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

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 for detailed information about API limits and optimization strategies.

Was this article helpful?