Import Knowledge Base Articles

POST /import - Import Knowledge Base Articles

Import or update knowledge base articles with multilingual content support. This endpoint handles creating new articles or updating existing ones based on correlation IDs.

Endpoint

POST /v1/knowledgebase/import

Request Headers

Header

Value

Required

Authorization

Bearer YOUR_API_TOKEN

Yes

Content-Type

application/json

Yes

Request Body Parameters

Parameter

Type

Required

Description

articles

array

Yes

Array of articles to import. At least one article is required

config

object

No

Configuration options for the import process

Article Object (articles[])

Parameter

Type

Required

Description

Example

correlationId

string

No

Unique identifier for article correlation. Use for updates

"article-001"

categoryCorrelationId

string

No

Category correlation ID for article organization

"tutorials"

isPrivate

boolean

No

Whether article is private (not visible to end users)

false

isHidden

boolean

No

Whether article is hidden from navigation/search

false

order

integer

No

Display order within category (1-based)

5

isFeatured

boolean

No

Whether article should be featured

true

featuredOrder

integer

No

Order for featured articles display

1

alternateSlugs

object

No

Alternative slugs by language for URL redirection

{"en": ["old-slug"], "es": ["viejo-slug"]}

contents

array

No

Content items in different languages

See Content Object below

Content Object (contents[])

Parameter

Type

Required

Description

Example

correlationId

string

No

Unique identifier for content correlation

"content-en-001"

lang

string

Yes

Language code (ISO 639-1 format)

"en", "es", "fr"

title

string

No

Article title in this language

"Getting Started Guide"

slug

string

No

URL-safe slug (auto-generated if not provided)

"getting-started"

content

string

No

Main article content

`"# Welcome

This guide..."`

keywords

string

No

SEO keywords

"tutorial, guide, setup"

lead

string

No

Article excerpt or summary

"Learn the basics..."

format

string

Yes

Content format: "markdown"
(for now, only Markdown)

"markdown"

createNewVersion

boolean

No

Create new version instead of updating

false

publishStatus

string

No

Publishing status: "published" or "unpublished"

"published"

featuredOrder

integer

No

Featured content display order

1

Config Object (config)

Parameter

Type

Required

Description

Example

slugConflictHandling

string

No

How to handle slug conflicts: "error" (default) or "auto-number"

"auto-number"

ignoreImportErrors

boolean

No

Allow partial imports by ignoring non-serious errors

false

includeContentInResponse

boolean

No

Include full content details in response

false

Example Request

Request Body:

{
  "articles": [
    {
      "correlationId": "getting-started-001",
      "categoryCorrelationId": "tutorials",
      "isPrivate": false,
      "contents": [
        {
          "lang": "en",
          "title": "Getting Started Guide",
          "content": "# Welcome\n\nThis guide will help you get started with our platform quickly and easily.",
          "keywords": "getting started, tutorial, guide",
          "format": "markdown",
          "publishStatus": "published"
        }
      ]
    }
  ]
}

Response Format

Success Response (200 OK)

{
  "errors": [],
  "results": [
    {
      "correlationId": "article-001",
      "articleId": 123,
      "status": "created",
      "categoryId": 456,
      "isPrivate": false,
      "isHidden": false,
      "isFeatured": true,
      "featuredOrder": 1,
      "order": 5,
      "version": "v1",
      "alternateSlugs": "{\"en\":[\"old-slug\"]}",
      "contents": [
        {
          "correlationId": "content-en-001",
          "lang": "en",
          "contentId": 789,
          "slug": "getting-started",
          "status": "created",
          "published": true,
          "title": "Getting Started Guide",
          "content": "# Welcome...",
          "keywords": "tutorial, guide",
          "lead": "Learn the basics..."
        }
      ],
      "errors": []
    }
  ]
}

Status Values

Article Status Values

  • created: New article was created
  • updated: Existing article was updated
  • error: Article processing failed

Content Status Values

  • created: New content was created
  • updated: Existing content was updated
  • error: Content processing failed

Article Ordering System

Understanding how article positioning works is crucial for proper content organization:

Order Field

  • Scope: Per category (within each category)
  • Behavior: Determines the display order of articles within their assigned category
  • Auto-assignment: When creating new articles, the order is automatically set to (current_articles_in_category + 1)
  • Manual control: You can specify a custom order value to position articles precisely within their category
  • Scope: Global (across all articles)
  • Behavior: Determines the display order for articles marked as isFeatured: true
  • Usage: Featured articles appear in a special "featured" section, ordered by this field
  • Default: 0 (not featured) when isFeatured: false

Examples

Category-based ordering:

{
  "correlationId": "tutorial-basic",
  "categoryCorrelationId": "tutorials", 
  "order": 1,                    // First article in "tutorials" category
  "isFeatured": false
}

Featured article ordering:

{
  "correlationId": "important-announcement",
  "categoryCorrelationId": "news",
  "order": 5,                    // 5th article in "news" category  
  "isFeatured": true,
  "featuredOrder": 1             // First in global featured section
}

Content Versioning System

Each article can have multiple content versions in each language. Understanding when to create new versions vs updating existing ones is important for content management:

Create New Version (createNewVersion: true)

  • Purpose: Preserves the current version and creates a completely new version
  • Use case: Major content updates, A/B testing, keeping revision history
  • Behavior: Current version remains unchanged, new version is created with your content
  • Publishing: New version starts as unpublished by default (unless you specify publishStatus: "published")

Update Existing Version (createNewVersion: false or omitted)

  • Purpose: Modifies existing content with intelligent version selection
  • Selection logic:
  • First priority: Published content (only one version per language can be published)
  • Fallback: Most recently created content if no published version exists
  • Intuitive behavior: Updates the published version when available, as expected by most users
  • Fallback behavior: Only updates drafts/unpublished content when no published version exists
  • Best practice: Still recommend using content correlationId for precise version targeting
  • Use case: Minor edits, corrections, updates to existing content
  • Behavior: Overwrites the selected existing content version
  • Publishing: Maintains current publishing status of the selected version (unless you specify publishStatus)

Version Management Examples

Creating a new version (keeping history):

{
  "correlationId": "user-guide-001",
  "contents": [
    {
      "correlationId": "guide-en-v2",
      "lang": "en",
      "title": "Updated User Guide",
      "content": "# Version 2.0\n\nMajor updates to the user guide...",
      "format": "markdown",
      "createNewVersion": true,        // Creates new version
      "publishStatus": "unpublished"   // New version starts as draft
    }
  ]
}

Updating existing version (quick edit):

{
  "correlationId": "user-guide-001", 
  "contents": [
    {
      "correlationId": "guide-en-published",    // Target specific version by correlation ID
      "lang": "en",
      "title": "User Guide (Updated)",
      "content": "# User Guide\n\nFixed typos and updated screenshots...",
      "format": "markdown",
      "createNewVersion": false        // Updates existing version
      // publishStatus omitted = keeps current status
    }
  ]
}

Advanced approach for precise version targeting:

// For maximum control, use correlation IDs to target specific versions
{
  "correlationId": "user-guide-001",
  "contents": [
    {
      "correlationId": "guide-en-v1-published",  // Target specific version by ID
      "lang": "en", 
      "title": "Updated Published Guide",
      "content": "Updated content for the live version...",
      "format": "markdown",
      "createNewVersion": false
    }
  ]
}

Version selection behavior:

// Scenario: Article has 3 content versions for language "en"
// Version 1: Created 2024-01-01, Unpublished (draft)
// Version 2: Created 2024-01-15, Unpublished (draft)  
// Version 3: Created 2024-01-10, Published ✅ (only one can be published per language)

// This update will modify Version 3 (the published version) ✅
{
  "correlationId": "article-001",
  "contents": [
    {
      "lang": "en",
      "title": "Updated Title",
      "createNewVersion": false    // Updates Version 3 (published version)
    }
  ]
}

// If no published versions exist, falls back to most recent
// All drafts scenario: Version A (2024-01-01, Draft), Version B (2024-01-15, Draft)
// Result: Would update Version B (most recent draft)

Version workflow example:

  • Initial version: createNewVersion: false (creates first version)
  • Minor edits: createNewVersion: false (updates published version if available, otherwise most recent)
  • Major rewrite: createNewVersion: true (preserves old, creates new)
  • Publish new: Update with publishStatus: "published"

Slug Management System

Slugs are URL-friendly identifiers used to access articles. Understanding how slug generation and conflict resolution works is essential for SEO and URL management:

Auto-Generation from Title

When you don't provide a slug field during content creation, the system automatically generates one from the article title:

  • Only on create: Auto-generation happens only when creating new content versions
  • On update: When updating existing content, the current slug value is preserved if no slug is provided
  • Source: Uses the title field from content
  • Process: Converts title to URL-safe format (lowercase, spaces to hyphens, special characters removed)
  • Language-specific: Each language gets its own slug based on its title
  • Uniqueness: Must be unique within the same language

Manual Slug Assignment

You can specify custom slugs for precise URL control:

{
  "lang": "en",
  "title": "Advanced User Guide for Professionals",
  "slug": "pro-user-guide",        // Custom slug instead of auto-generated
  "content": "...",
  "format": "markdown"
}

Slug Conflict Resolution

When slug conflicts occur (duplicate slugs in the same language), you have two options:

Option 1: Error on Conflict (Default)

{
  "config": {
    "slugConflictHandling": "error"    // Default behavior
  }
}
  • Behavior: API returns error when slug conflict detected
  • Response: "Slug 'getting-started' for language 'en' is already in use"
  • Use case: When you want full control and need to resolve conflicts manually

Option 2: Auto-Number Resolution

{
  "config": {
    "slugConflictHandling": "auto-number"
  }
}
  • Behavior: Automatically appends numbers to make slugs unique
  • Examples: getting-startedgetting-started-2getting-started-3
  • Use case: Bulk imports where some conflicts are acceptable

Slug Examples

Auto-generated slugs (on create):

// Creating new content - slug auto-generated from title
{
  "lang": "en",
  "title": "Getting Started Guide",     // → slug: "getting-started-guide" (auto-generated)
  "content": "...",
  "format": "markdown"
  // No slug provided, so auto-generated
}

// More examples:
// "FAQ & Troubleshooting" → slug: "faq-troubleshooting"  
// "User Management (Admin)" → slug: "user-management-admin"

Slug behavior on update:

// Updating existing content - slug preserved
{
  "correlationId": "existing-content-en",
  "lang": "en", 
  "title": "Updated Getting Started Guide",  // Title changed
  "content": "Updated content...",
  "format": "markdown"
  // No slug provided → keeps existing slug "getting-started-guide"
  // Slug does NOT change to "updated-getting-started-guide"
}

// To change slug on update, explicitly provide it:
{
  "correlationId": "existing-content-en",
  "lang": "en",
  "title": "Updated Getting Started Guide",
  "slug": "new-getting-started-guide",     // Explicitly change slug
  "content": "Updated content...",
  "format": "markdown"
}

Manual slugs with conflict resolution:

{
  "articles": [
    {
      "correlationId": "guide-1",
      "contents": [
        {
          "lang": "en",
          "title": "Getting Started",
          "slug": "getting-started"      // First article gets this slug
        }
      ]
    },
    {
      "correlationId": "guide-2", 
      "contents": [
        {
          "lang": "en",
          "title": "Quick Start Guide",
          "slug": "getting-started"      // Conflict! Will become "getting-started-2"
        }
      ]
    }
  ],
  "config": {
    "slugConflictHandling": "auto-number"
  }
}

Multilingual slug management:

{
  "contents": [
    {
      "lang": "en",
      "title": "User Guide",
      "slug": "user-guide"             // English slug
    },
    {
      "lang": "es", 
      "title": "Guía del Usuario",
      "slug": "guia-usuario"          // Spanish slug (different from English)
    },
    {
      "lang": "fr",
      "title": "Guide Utilisateur"
      // No slug provided → auto-generated: "guide-utilisateur"
    }
  ]
}

Best Practices for Slugs

  • SEO-friendly: Use descriptive, keyword-rich slugs
  • Consistent format: Stick to lowercase, hyphens for spaces
  • Language appropriate: Use language-specific slugs for better localization
  • Avoid conflicts: Check existing slugs before bulk imports
  • Auto-numbering for imports: Use auto-number for large batch imports
  • Manual for important pages: Specify custom slugs for key articles

Best Practices

  • Use Correlation IDs: Always provide correlation IDs for articles and content you want to update later
  • Handle Conflicts: Set appropriate slug conflict handling based on your needs
  • Test First: Use the test environment to validate your import payload before production. ⚠️ Warning: The API can overwrite all your content and changes are not revertible. Always backup your data using GET endpoints before making changes
  • Language Consistency: Ensure language codes are consistent across your content
  • Content Validation: Validate markdown/HTML content before importing

Common Error Scenarios

  • Missing Required Fields: Ensure lang and format are provided for all content
  • Invalid Correlation IDs: Check that correlation IDs don't contain invalid characters
  • Slug Conflicts: Use auto-numbering or ensure unique slugs when creating content
  • Category References: Verify that category correlation IDs exist before referencing them
  • Content Format: Ensure content matches the specified format (markdown/html)

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., Article[0], Article[1].contents[0]) to help you identify exactly which item in your request caused the issue.

Validation Errors

{
  "errors": [
    "Too many articles for import. Maximum allowed: 50, provided: 75",
    "Article[0]: Too many languages per article. Maximum allowed: 20, provided: 25",
    "Article[1]: Language 'en' is required for content",
    "Article[2]: Content format 'html' is required but not provided",
    "Article[3]: Article with correlation ID 'duplicate-id' appears multiple times in request"
  ]
}

Content Validation Errors

{
  "errors": [
    "Article[0].contents[0]: Title is required when creating new content",
    "Article[1].contents[1]: Invalid language code 'english' - use ISO 639-1 format (e.g., 'en')",
    "Article[2].contents[0]: Slug 'getting-started' for language 'en' is already in use. Use slugConflictHandling: 'auto-number' to automatically resolve conflicts.",
    "Article[3].contents[0]: Manual slug_state requires a non-empty slug value",
    "Article[4].contents[0]: Invalid publish status 'draft' - use 'published' or 'unpublished'"
  ]
}

Category Reference Errors

{
  "errors": [
    "Article[0]: Category with correlation ID 'non-existent-category' not found",
    "Article[1]: Category correlation ID cannot be empty string",
    "Article[2]: Invalid category correlation ID format"
  ]
}

Content Update Errors

{
  "errors": [
    "Article[0].contents[0]: Content with correlation ID 'missing-content' not found for update",
    "Article[1].contents[0]: Cannot update content - article with correlation ID 'missing-article' not found",
    "Article[2].contents[0]: Language 'es' content not found in existing article 'help-guide'"
  ]
}

Request Format Errors

{
  "error": "Body not present"
}
{
  "error": "Invalid request body - malformed JSON"
}

Mixed Errors (with ignoreImportErrors: true)

{
  "errors": [
    "Article[0]: Category 'tutorials' not found - article created without category",
    "Article[2]: Slug conflict resolved: 'getting-started' changed to 'getting-started-2'",
    "Article[4]: Content validation failed - title missing, using 'Untitled' as default"
  ],
  "results": [
    {
      "correlationId": "article-001",
      "status": "created",
      "articleId": 123
    },
    {
      "correlationId": "article-003", 
      "status": "created",
      "articleId": 124
    }
  ]
}

Examples

Example 1: Simple Article Import

Create a new article with English content:

{
  "articles": [
    {
      "correlationId": "getting-started-001",
      "categoryCorrelationId": "tutorials",
      "isPrivate": false,
      "contents": [
        {
          "lang": "en",
          "title": "Getting Started Guide",
          "content": "# Welcome to Our Platform\n\nThis guide will help you get started with our platform quickly and easily.\n\n## First Steps\n\n1. Create your account\n2. Set up your profile\n3. Explore the dashboard",
          "keywords": "getting started, tutorial, guide, setup",
          "lead": "Learn the essential steps to get started with our platform",
          "format": "markdown",
          "publishStatus": "published"
        }
      ]
    }
  ]
}

Example 2: Multilingual Article with Features

Create a featured article with multiple languages:

{
  "articles": [
    {
      "correlationId": "advanced-features-001",
      "categoryCorrelationId": "advanced",
      "isPrivate": false,
      "isFeatured": true,
      "featuredOrder": 1,
      "order": 10,
      "alternateSlugs": {
        "en": ["advanced-guide", "pro-features"],
        "es": ["funciones-avanzadas"]
      },
      "contents": [
        {
          "correlationId": "content-en-advanced",
          "lang": "en",
          "title": "Advanced Features Guide",
          "slug": "advanced-features",
          "content": "# Advanced Features\n\nExplore the powerful advanced features...",
          "keywords": "advanced, features, pro, expert",
          "lead": "Master the advanced capabilities of our platform",
          "format": "markdown",
          "publishStatus": "published"
        },
        {
          "correlationId": "content-es-advanced",
          "lang": "es",
          "title": "Guía de Funciones Avanzadas",
          "slug": "funciones-avanzadas",
          "content": "# Funciones Avanzadas\n\nExplora las potentes funciones avanzadas...",
          "keywords": "avanzado, funciones, pro, experto",
          "lead": "Domina las capacidades avanzadas de nuestra plataforma",
          "format": "markdown",
          "publishStatus": "published"
        }
      ]
    }
  ]
}

Example 3: Batch Import with Configuration

Import multiple articles with auto-numbering for slug conflicts:

{
  "articles": [
    {
      "correlationId": "faq-001",
      "categoryCorrelationId": "support",
      "contents": [
        {
          "lang": "en",
          "title": "Frequently Asked Questions",
          "content": "# FAQ\n\n## How do I reset my password?\n\n...",
          "format": "markdown",
          "publishStatus": "published"
        }
      ]
    },
    {
      "correlationId": "troubleshooting-001",
      "categoryCorrelationId": "support",
      "contents": [
        {
          "lang": "en",
          "title": "Troubleshooting Guide",
          "content": "# Troubleshooting\n\n## Common Issues\n\n...",
          "format": "markdown",
          "publishStatus": "unpublished"
        }
      ]
    }
  ],
  "config": {
    "slugConflictHandling": "auto-number",
    "ignoreImportErrors": true,
    "includeContentInResponse": true
  }
}

Example 4: Update Existing Article

Update an existing article by providing its correlation ID:

{
  "articles": [
    {
      "correlationId": "existing-article-001",
      "isPrivate": false,
      "isFeatured": true,
      "contents": [
        {
          "correlationId": "existing-content-en",
          "lang": "en",
          "title": "Updated Title",
          "content": "# Updated Content\n\nThis article has been updated with new information...",
          "format": "markdown",
          "createNewVersion": false,
          "publishStatus": "published"
        }
      ]
    }
  ]
}

Status Values

Article Status Values

  • created: New article was created
  • updated: Existing article was updated
  • error: Article processing failed

Content Status Values

  • created: New content was created
  • updated: Existing content was updated
  • error: Content processing failed

Rate Limits

  • Maximum 50 articles per import request
  • Maximum 20 content languages per article
  • Maximum 10 requests per minute
  • Maximum 1000 articles per hour

For larger imports, contact support for increased limits.

Additional Examples

Multilingual Article with Config (JSON)

Request Body:

{
  "articles": [
    {
      "correlationId": "advanced-guide-001",
      "categoryCorrelationId": "advanced",
      "isFeatured": true,
      "featuredOrder": 1,
      "contents": [
        {
          "correlationId": "content-en-advanced",
          "lang": "en",
          "title": "Advanced Features Guide",
          "content": "# Advanced Features\n\nExplore powerful advanced capabilities...",
          "format": "markdown",
          "publishStatus": "published"
        },
        {
          "correlationId": "content-es-advanced",
          "lang": "es",
          "title": "Guía de Funciones Avanzadas",
          "content": "# Funciones Avanzadas\n\nExplora las potentes funciones avanzadas...",
          "format": "markdown",
          "publishStatus": "published"
        }
      ]
    }
  ],
  "config": {
    "slugConflictHandling": "auto-number",
    "ignoreImportErrors": false,
    "includeContentInResponse": true
  }
}

Multilingual Article with Config (cURL)

curl -X POST "https://api.productfruits.com/v1/knowledgebase/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "articles": [
      {
        "correlationId": "advanced-guide-001",
        "categoryCorrelationId": "advanced",
        "isFeatured": true,
        "featuredOrder": 1,
        "contents": [
          {
            "correlationId": "content-en-advanced",
            "lang": "en",
            "title": "Advanced Features Guide",
            "content": "# Advanced Features\\n\\nExplore powerful advanced capabilities...",
            "format": "markdown",
            "publishStatus": "published"
          },
          {
            "correlationId": "content-es-advanced",
            "lang": "es",
            "title": "Guía de Funciones Avanzadas",
            "content": "# Funciones Avanzadas\\n\\nExplora las potentes funciones avanzadas...",
            "format": "markdown",
            "publishStatus": "published"
          }
        ]
      }
    ],
    "config": {
      "slugConflictHandling": "auto-number",
      "ignoreImportErrors": false,
      "includeContentInResponse": true
    }
  }'

Images and Media

Using Images in Articles

Images must be uploaded separately using the /upload-image endpoint before referencing them in article content.

Workflow for including images:

  • Upload the image using POST /upload-image
  • Get the image URL from the upload response
  • Reference the image in your article content using markdown or HTML

Example workflow:

# Step 1: Upload image
curl -X POST "https://api.productfruits.com/v1/knowledgebase/upload-image" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "file=@screenshot.png"

# Response: { "imageId": "abc123", "imageUrl": "https://cdn-assets.productfruits.com/abc123" }
// Step 2: Use image URL in article import
{
  "articles": [{
    "correlationId": "tutorial-001", 
    "contents": [{
      "lang": "en",
      "title": "Tutorial with Screenshots",
      "content": "# Getting Started\n\n![Step 1](https://cdn-assets.productfruits.com/abc123)\n\nFollow these steps...",
      "format": "markdown"
    }]
  }]
}

Supported Image Formats

  • JPG/JPEG: Best for photographs
  • PNG: Best for screenshots, logos, images with transparency
  • GIF: Supported for simple animations
  • WebP: Modern format with excellent compression

Video Content

⚠️ Direct video uploads are not supported through the API.

Supported video embedding options:

  • YouTube: Embed using YouTube URLs or iframe codes
  • Vimeo: Embed using Vimeo URLs or iframe codes
  • Loom: Embed using Loom URLs or iframe codes

Example video embedding:

# Tutorial Video

Watch this tutorial to get started:

[Watch on YouTube](https://www.youtube.com/watch?v=VIDEO_ID)

Or embed directly:
<iframe src="https://www.youtube.com/embed/VIDEO_ID" frameborder="0" allowfullscreen></iframe>

Media Best Practices

  • Upload images first: Always upload images via /upload-image before importing articles
  • Use descriptive alt text: Include meaningful alt attributes for accessibility
  • Optimize file sizes: Compress images before upload (max 10MB per image)
  • External video hosting: Use YouTube, Vimeo, or Loom for video content
  • Test media links: Verify all media URLs are accessible before importing

Rate Limiting

Please see our guide for detailed information about API limits and optimization strategies.

Additional Examples

Basic Article Import (cURL)

curl -X POST "https://api.productfruits.com/v1/knowledgebase/import" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "articles": [
      {
        "correlationId": "getting-started-001",
        "categoryCorrelationId": "tutorials",
        "isPrivate": false,
        "contents": [
          {
            "lang": "en",
            "title": "Getting Started Guide",
            "content": "# Welcome\\n\\nThis guide will help you get started with our platform quickly and easily.",
            "keywords": "getting started, tutorial, guide",
            "format": "markdown",
            "publishStatus": "published"
          }
        ]
      }
    ]
  }'


Was this article helpful?