Skip to content

How to Export Desk365 Knowledge Base Data: API, Limits & Methods

Desk365 has no native KB export. Learn how to extract knowledge base articles via the v3 API, handle rate limits, attachments, and visibility mapping.

Roopi Roopi · · 19 min read
How to Export Desk365 Knowledge Base Data: API, Limits & Methods
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

How to Export Desk365 Knowledge Base Data: API, Limits & Methods

Info

TL;DR — Desk365 Knowledge Base Export

Desk365 has no native UI export for knowledge base articles. The admin Exports tab covers tickets, contacts, and companies — the KB is excluded. Your only first-party extraction path is the REST API (v3), which exposes endpoints for categories, folders, and articles. Plan for rate limits (100 calls/hour on Standard, 50/minute on Plus/Premium), manual attachment handling, and HTML-to-target conversion.

When you need to move a knowledge base out of Desk365 — whether for a Desk365 to Intercom migration, archival, or warehouse loading — the text is only half the problem. A production-grade extraction must preserve the structural hierarchy, article formatting, inline images, file attachments, visibility rules, and engagement metrics. Desk365 does not hand you any of this through a one-click export.

This guide covers the full extraction surface: what the API returns, what it doesn't, rate-limit math by plan tier, attachment handling gaps, and the practical edge cases you'll hit when pulling Desk365 KB data.

For a broader look at exporting tickets, contacts, and company records, see our companion guide on exporting all data from Desk365.

Desk365 Knowledge Base Data Model

Before you extract anything, understand the hierarchy. Desk365's knowledge base is organized into three levels:

  • Categories — top-level groupings (e.g., "Payments & Billing")
  • Folders — sub-groupings within categories (e.g., "Payment Methods" inside a "Billing Details" folder under "Payments & Billing")
  • Articles — the actual content, living inside folders

Each article can be in Draft (status 0) or Published (status 1) state. Desk365 supports article versioning in the UI: drafts increment as 0.1, 0.2; the first published version becomes 1.0; draft edits after publication become 1.1, 1.2; and the next publication becomes 2.0. The API, however, only returns the current version — historical versions are not exposed.

Info

No article limits: Desk365 allows unlimited knowledge base articles, even on the Standard plan.

What KB Data Can You Export from Desk365?

Object Native UI Export API Export (v3) Format Limitations
KB Categories No Yes JSON Includes visibility metadata; no CSV option
KB Folders No Yes JSON Parent category reference included
KB Articles No Yes JSON HTML + plain text body; drafts included; has_attachments flag only — not the files
Article Attachments No Partial Binary Flag returned, but files require separate download logic
Article Versions No No (current only) API returns the latest version; history not exposed
View/Like Counts No Yes JSON article_views, article_likes, article_dislikes fields included
Author/Editor Data No Yes JSON created_by_email and updated_by_email

The native UI export under Settings > Admin > Exports handles tickets, contacts, and companies — not knowledge base content. If you need KB data, the API is your only first-party path.

Method 1: Desk365 REST API (v3) — The Primary Extraction Path

Authentication and Base URL

API calls go through your tenant's subdomain: https://yoursubdomain.desk365.io. Each subdomain has its own API key, ensuring only authorized users access that tenant's data. Add your API key in the Authorization header of every request, and include /apis/v3 in the URL path.

You can find your API key under Settings > Integrations > API in the Desk365 admin panel.

curl -H "Authorization: YOUR_API_KEY" \
  "https://yoursubdomain.desk365.io/apis/v3/kb_categories"

A 200 response means you're authorized. A 401 means your key is wrong or expired.

KB Categories Endpoint

Retrieves all top-level categories with visibility settings and display ordering.

Key response fields:

Field Description
category_name Name of the category
category_description Description text
created_by_email Creator's email
created_on Creation timestamp
support_portal_visibility 1 = Not visible, 2 = All visitors, 3 = Signed-in users only, 4 = Specific companies
company_list Companies with access (when visibility = 4)
agent_portal_visibility 1 = All agents, 2 = Only agents in specified groups
agent_group_list Agent groups with access
category_order Display order in the KB
Warning

Migration trap: Visibility metadata matters. A category restricted to specific companies in Desk365 has no automatic equivalent in platforms like Zendesk Guide or Freshdesk. Map these visibility levels to your target's access-control model before import.

KB Folders Endpoint

Retrieves all folders with their parent category reference.

Key response fields:

Field Description
folder_name Folder name
category_name Parent category
created_by_email Creator's email
created_on Creation timestamp

KB Articles Endpoint

Retrieves articles with full content, metadata, and engagement metrics.

Key response fields:

Field Description
article_title Article title
article_content Full HTML body
article_content_text Plain text version
category_name Parent category
folder_name Parent folder
has_attachments Boolean — true if attachments exist
created_by_email Author email
updated_by_email Last editor email
created_on Creation timestamp
updated_on Last update timestamp
article_views View count
article_likes Like count
article_dislikes Dislike count
status 0 = Draft, 1 = Published

The article_content field returns HTML, not Markdown. Desk365's WYSIWYG editor supports rich formatting, inline images, tables, and custom HTML/CSS — the API output reflects all of it. If your target platform needs Markdown (e.g., GitBook, Notion), convert using libraries like turndown (JavaScript) or markdownify (Python). Watch for:

  • Inline images with Desk365-hosted URLs that will break after migration
  • Custom CSS classes that carry no semantic meaning in the target
  • Table structures that don't survive naive HTML-to-Markdown conversion

Desk365 also returns null and empty-string fields as null, so build null-safe transforms in your extraction scripts.

Useful recent change: Desk365 announced in October 2025 that KB article URLs are now included in API responses. This simplifies redirect mapping and source-to-target article traceability during migration. (desk365.io)

Rate Limits by Plan

Desk365 enforces plan-specific API rate limits:

Plan Rate Limit Effective KB Articles/Hour*
Standard ($12/user/mo) 100 API calls per hour ~100 articles
Plus ($22/user/mo) 50 API calls per minute ~3,000 articles
Premium ($32/user/mo) 50 API calls per minute ~3,000 articles

*Assumes one API call returns one page of articles. Actual throughput depends on pagination and whether you also need to fetch categories, folders, and attachment data.

Danger

Standard plan bottleneck: At 100 calls/hour, exporting a knowledge base with 500+ articles plus their categories and folders could take several hours. If you're on Standard and planning a migration, factor this into your timeline — or temporarily upgrade to Plus.

The gap between Standard (hourly cap) and Plus/Premium (per-minute cap) is significant. At 100 calls/hour, Standard plan users are effectively limited to 1 request every 36 seconds. Plus/Premium users get 50 requests per minute — sustained, with no hourly ceiling. For a 500-article KB, assuming one article per API call plus overhead for category and folder fetches, Standard plan extraction would take approximately 5–6 hours of wall-clock time. Plus/Premium users can complete the same extraction in under 15 minutes.

When you hit a 429 Too Many Requests response, implement exponential backoff. Read the Retry-After header if present, or pause for 60 seconds before retrying. For Standard plan users, inserting a time.sleep(36) between calls is a reasonable conservative baseline. Do not write scripts that fail silently on 429s — you will end up with missing articles and no indication of where the gap is.

Pagination behavior: Desk365 documents detailed pagination for tickets and time entries (including 30/50/100 record pages and offset parameters), but publishes no equivalent detail for KB endpoints. In testing, KB article endpoints behave differently from ticket endpoints — do not assume identical pagination. Verify page size and offset behavior against your own tenant before building extraction scripts. The safest approach: test with a small category first, compare the article count to the UI, and confirm your pagination loop isn't stopping early.

Paginated Article Extraction — Working Python Script

The following script handles rate-limit backoff and writes all articles to a structured JSON file. It is written for Standard plan users (100 calls/hour); Plus/Premium users can reduce the sleep interval proportionally.

import requests
import json
import time
 
API_KEY = "YOUR_API_KEY"
SUBDOMAIN = "yoursubdomain"
BASE_URL = f"https://{SUBDOMAIN}.desk365.io/apis/v3"
HEADERS = {"Authorization": API_KEY}
 
# Adjust for your plan: Standard = 36s, Plus/Premium = 1.2s
REQUEST_DELAY_SECONDS = 36
MAX_RETRIES = 5
 
def get_with_backoff(url, params=None):
    """GET request with exponential backoff on 429."""
    for attempt in range(MAX_RETRIES):
        response = requests.get(url, headers=HEADERS, params=params)
        if response.status_code == 200:
            return response.json()
        elif response.status_code == 429:
            wait = (2 ** attempt) * 60  # 60s, 120s, 240s, ...
            print(f"Rate limited. Waiting {wait}s before retry {attempt + 1}/{MAX_RETRIES}")
            time.sleep(wait)
        elif response.status_code == 401:
            raise Exception("Authentication failed. Check your API key.")
        else:
            raise Exception(f"Unexpected status {response.status_code}: {response.text}")
    raise Exception(f"Max retries exceeded for URL: {url}")
 
def fetch_all_articles():
    """Fetch all KB articles with pagination."""
    articles = []
    page = 1
    page_size = 100  # Verify this against your tenant's actual behavior
 
    while True:
        print(f"Fetching articles page {page}...")
        params = {"page": page, "per_page": page_size}
        data = get_with_backoff(f"{BASE_URL}/kb_articles", params=params)
 
        batch = data if isinstance(data, list) else data.get("articles", [])
        if not batch:
            print(f"No more articles found at page {page}. Done.")
            break
 
        articles.extend(batch)
        print(f"  Retrieved {len(batch)} articles (total so far: {len(articles)})")
 
        # Stop if this page returned fewer items than page_size
        if len(batch) < page_size:
            break
 
        page += 1
        time.sleep(REQUEST_DELAY_SECONDS)
 
    return articles
 
def fetch_categories():
    data = get_with_backoff(f"{BASE_URL}/kb_categories")
    time.sleep(REQUEST_DELAY_SECONDS)
    return data if isinstance(data, list) else data.get("categories", [])
 
def fetch_folders():
    data = get_with_backoff(f"{BASE_URL}/kb_folders")
    time.sleep(REQUEST_DELAY_SECONDS)
    return data if isinstance(data, list) else data.get("folders", [])
 
if __name__ == "__main__":
    print("Starting Desk365 KB export...")
 
    categories = fetch_categories()
    print(f"Fetched {len(categories)} categories.")
 
    folders = fetch_folders()
    print(f"Fetched {len(folders)} folders.")
 
    articles = fetch_all_articles()
    print(f"Fetched {len(articles)} articles total.")
 
    output = {
        "exported_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
        "categories": categories,
        "folders": folders,
        "articles": articles,
    }
 
    with open("desk365_kb_export.json", "w", encoding="utf-8") as f:
        json.dump(output, f, ensure_ascii=False, indent=2)
 
    print("Export complete. Output: desk365_kb_export.json")
 
    # Validation: flag articles with has_attachments=True
    articles_with_attachments = [a for a in articles if a.get("has_attachments")]
    if articles_with_attachments:
        print(f"\nWARNING: {len(articles_with_attachments)} article(s) have attachments "
              f"that require separate download. Article IDs:")
        for a in articles_with_attachments:
            print(f"  - {a.get('article_title', 'Unknown')} (has_attachments=True)")
Warning

Verify pagination before running at scale. The page and per_page parameter names and behavior above reflect common Desk365 API patterns. Test against a small category in your tenant and compare the count to the UI before running the full export. KB endpoints may differ from ticket endpoints in their pagination implementation.

Method 2: Web Scraping the Public Help Center

If your knowledge base is publicly accessible through the Desk365 support portal, web scraping is technically possible. This is a fallback — not a recommended primary method — but it works when:

  • You've lost API access (expired subscription, key revoked)
  • You need to capture the rendered HTML exactly as customers see it
  • You want to archive the public-facing version including custom CSS/branding

How to Scrape Desk365 KB

  1. Identify the index page — Desk365 help centers typically expose a category listing at the root URL
  2. Crawl category → folder → article links — follow the hierarchy
  3. Extract article title, body HTML, and metadata from each page's DOM
  4. Download embedded images — rewrite src URLs to local paths
import requests
from bs4 import BeautifulSoup
 
base_url = "https://help.yourcompany.desk365.io"
response = requests.get(f"{base_url}/en/")
soup = BeautifulSoup(response.text, "html.parser")
 
# Extract article links from category pages
article_links = [a["href"] for a in soup.select("a[href*='/articles/']")]
 
for link in article_links:
    article_resp = requests.get(link)
    article_soup = BeautifulSoup(article_resp.text, "html.parser")
    title = article_soup.select_one("h1").text
    body = article_soup.select_one(".article-content")  # selector varies
    print(f"Extracted: {title}")
Warning

What you lose with scraping:

  • Draft articles (not publicly visible)
  • Author emails, timestamps, and edit history
  • Engagement metrics (views, likes, dislikes)
  • Visibility and access-control settings
  • Clean folder/category hierarchy (must be inferred from URL structure)
  • Attachments that aren't inline images

The API gives you the full dataset. Scraping gives you the public-facing subset only.

Method 3: Power Automate Connector

Desk365 integrates with Microsoft Power Automate, but the connector focuses on ticket operations — triggers include ticket creation, ticket updates, and note additions.

The Power Automate connector does not expose knowledge base endpoints (categories, folders, or articles). If you need KB data through a low-code interface, use Power Automate's HTTP action to call the Desk365 API directly with the same authentication pattern described above.

Handling Attachments and Inline Images

This is where most knowledge base migrations break. Extracting text is straightforward; extracting and re-hosting assets requires specific logic.

The Attachment Gap

The API response includes a has_attachments boolean flag on each article, but it does not return the attachment files inline or provide direct download URLs in the standard KB articles endpoint. You know that attachments exist, but you don't get them automatically.

What Desk365 Attachment URLs Look Like

From testing Desk365 help centers, inline images in article_content HTML appear as <img> tags with src values pointing to Desk365's cloud storage — typically in one of these forms:

https://d3vjblah4x5uuu.cloudfront.net/assets/desk365/TENANT_ID/kb/images/FILENAME.png
https://yoursubdomain.desk365.io/assets/kb/images/FILENAME.png

These URLs are generally publicly accessible CDN links for published articles and do not require authentication headers to download. Draft article images may be scoped differently — test with a draft article in your tenant to confirm.

File attachments (PDFs, ZIPs, spreadsheets) linked from article content follow a similar pattern but may use signed URLs with expiry. Download all assets during your initial extraction window rather than deferring — a signed URL that works today may return 403 in 48 hours.

To extract inline assets from article_content:

  1. Parse the HTML with BeautifulSoup (Python) or Cheerio (Node.js). Do not use regex for HTML parsing — nested tags and attribute variations will cause silent data loss.
  2. Find all <img> tags and <a> tags where href points to a Desk365 domain.
  3. Attempt the download. Log the HTTP status code for every asset. A 200 means success; a 403 means authentication is required; a 404 means the file no longer exists in Desk365's storage.
  4. Store downloaded files with a naming convention that includes the source article identifier (e.g., article_12345_filename.png) so you can reattach them in the target system.
  5. Replace the old Desk365 src/href URL in article_content with the new URL or local path before importing.
import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse
import os
 
DESK365_DOMAINS = ("desk365.io", "cloudfront.net")
 
def extract_and_download_assets(article_id, html_content, output_dir):
    """
    Parse article HTML, download all Desk365-hosted assets,
    and rewrite URLs to local paths.
    Returns the modified HTML string.
    """
    soup = BeautifulSoup(html_content, "html.parser")
    os.makedirs(output_dir, exist_ok=True)
 
    for tag, attr in [("img", "src"), ("a", "href")]:
        for element in soup.find_all(tag):
            url = element.get(attr, "")
            if not url or not any(d in url for d in DESK365_DOMAINS):
                continue
 
            filename = f"article_{article_id}_{os.path.basename(urlparse(url).path)}"
            local_path = os.path.join(output_dir, filename)
 
            try:
                resp = requests.get(url, timeout=30)
                resp.raise_for_status()
                with open(local_path, "wb") as f:
                    f.write(resp.content)
                element[attr] = local_path
                print(f"  Downloaded: {url} -> {local_path}")
            except requests.HTTPError as e:
                print(f"  FAILED [{e.response.status_code}]: {url}")
                # Do not silently skip — log for manual review
 
    return str(soup)

Your options when has_attachments is True but no file URL appears in the HTML:

  1. Parse the article_content HTML for <img>, <a>, and other tags pointing to Desk365-hosted files and download those URLs.
  2. Contact Desk365 support to ask about bulk attachment export. For large migrations, they may provide a data dump or advise on the correct endpoint.
  3. Scrape attachment URLs from the rendered help center as a supplement to the API extraction.

Handling Visibility and Access Control

Desk365's KB has a nuanced visibility model that most target platforms don't replicate exactly. You can set visibility per category — public, private, restricted to internal agents — and limit access to users from specific companies or agent groups.

Capture the visibility fields (support_portal_visibility, agent_portal_visibility, company_list, agent_group_list) during export and build a mapping table to your target's access model.

Desk365 Visibility Value Meaning Zendesk Guide Equivalent Freshdesk Equivalent
support_portal_visibility = 1 Not visible on support portal N/A (unpublish) N/A (unpublish)
support_portal_visibility = 2 All visitors Public article Public article
support_portal_visibility = 3 Signed-in users only Signed-in users section Logged-in users
support_portal_visibility = 4 Specific companies User segments (manual setup required) Company-restricted (requires workaround)
agent_portal_visibility = 1 All agents Internal article Agent-only article
agent_portal_visibility = 2 Specific agent groups Internal + group restriction Department-restricted
Warning

Do not flatten permissions silently. If you import an internal SOP as a public article, you risk a data exposure incident. If your destination only supports broad visibility buckets, capture the original access model in a sidecar mapping file so the decisions are explicit and auditable.

Note on competitor equivalences: Zendesk Guide's user segments are available on Suite Growth and above. Freshdesk's company-restricted KB requires Portal customization and is not a native out-of-box feature on all plans. Verify your target platform's plan supports the access control granularity you need before migrating restricted content.

Multi-Brand Knowledge Base Considerations

Desk365 allows you to create distinct help centers with different content and branding for different customer segments or product lines. Each brand's KB content is scoped separately.

When exporting:

  • Enumerate all brands/help centers before starting extraction
  • Tag each article with its brand origin
  • Preserve brand-specific URLs for redirect mapping post-migration

Step-by-Step: Full KB Export via API

Step 1: Freeze Scope

Decide whether your export must include drafts, published-only content, company-restricted content, department-restricted articles, trashed articles you plan to restore, and multiple brands. In Desk365, those are real differences, not cleanup details.

Also note: deleting a category removes all associated folders and articles. Do not do admin cleanup in production until you have a complete snapshot.

Step 2: Authenticate and Test

Grab your API key from Settings > Integrations > API. Test a basic call:

curl -H "Authorization: YOUR_API_KEY" \
  "https://yoursubdomain.desk365.io/apis/v3/kb_categories"

A 200 response confirms authentication. A 401 means the key is wrong, revoked, or expired.

Step 3: Export Categories

Fetch all categories. Store category_name, category_order, and all visibility fields. You need these to reconstruct the hierarchy and map access control in the target.

Step 4: Export Folders

Fetch all folders. Map each folder_name to its parent category_name.

Step 5: Export Articles

Use the paginated extraction script above. For each article, store:

  • Title and content (HTML + plain text)
  • Category and folder references
  • Status (draft vs. published)
  • Author and editor emails
  • Timestamps
  • View/like/dislike counts
  • has_attachments flag
  • Article URL (available in API responses as of October 2025)

Step 6: Download Inline Assets

Run the asset extraction function against each article's article_content HTML. Log every download attempt with HTTP status code. A 0-byte file or a 403 response both indicate a failed asset extraction — do not treat them as successes.

Step 7: Map Authors

The API returns created_by_email and updated_by_email. Match these to user accounts in your target system. If the email addresses don't exist on the destination platform, most import APIs will either reject the payload or assign all articles to the admin user — destroying content attribution.

Build a mapping table before import:

  1. Extract the unique author/editor emails from your export.
  2. Create or verify those users in the target platform.
  3. Map source emails to target user IDs.

Step 8: Validate Completeness

Compare the count of exported articles against the Desk365 admin panel count. Verify that:

  • Draft articles are included if needed
  • Every category has its expected folders
  • No articles were skipped due to rate-limiting errors (check your script's retry log)
  • No article_content fields returned null
  • Downloaded assets are not 0-byte files
  • Every article has a valid category/folder reference in your extracted hierarchy
  • Articles flagged with has_attachments=True have corresponding downloaded files

SEO and URL Redirect Mapping

If your Desk365 knowledge base is public, search engines have indexed your article URLs. When you migrate, your domain structure and URL slugs change. Without 301 redirects, customers clicking Google results or bookmarked links will hit 404 errors.

To prevent SEO regression:

  1. Extract the public URL of every Desk365 article during your API pull (article URLs are included in API responses as of October 2025).
  2. After importing articles into your new platform, extract the new public URLs.
  3. Create a mapping CSV: old_url, new_url — one row per article.
  4. Configure 301 redirects at your DNS/proxy layer (e.g., Cloudflare Page Rules or Transform Rules) or your new platform's redirect manager.
Warning

Internal article links break too. If articles reference other Desk365 articles (e.g., <a href="https://yourdomain.desk365.io/support/solutions/articles/12345">), those links will be dead after cutover. Build a translation map of old article URLs to new article URLs and run a search-and-replace on all article_content HTML before importing. This is most easily done after both old and new URLs are known — i.e., after the initial import with dummy links, not before.

Common Edge Cases and Failure Modes

HTML formatting inconsistencies. Articles created with the WYSIWYG editor may contain nested <div> tags, empty <p> elements, and inline styles. Clean the HTML with a library like bleach (Python) before importing to your target.

No article version history in the API. Desk365 supports versioning in the UI — tracking changes, comparing versions, and reverting to previous versions. This history is not exposed through the API. If you need historical versions, request a data dump from Desk365 support before canceling your subscription.

Deleted content. Desk365 lets agents move articles to trash, restore them as drafts, or permanently clear trash. The API does not expose a trash or deleted-items endpoint. If your migration scope includes deleted content, recover it in the Desk365 UI before pulling the final export.

Multilingual content. Desk365 supports creating KB articles in multiple languages for localized support. In testing, the v3 KB articles endpoint does not return a dedicated language field — language appears to be implicit in article content rather than a structured metadata field. If you have a multilingual KB, audit a sample of articles via the API to confirm how language is represented in your specific instance before building extraction logic around it.

Draft articles in the export. The API returns both draft and published articles. Filter on status == 1 if you only want published content. If migrating everything, confirm your target platform supports a draft state — some platforms import all articles as published regardless of the source field.

Rate-limit 429 errors causing silent gaps. Scripts that catch a 429 and continue without retrying will produce an export that looks complete but is missing articles. Use the backoff script above and log every 429 with the URL and page number so you can audit for gaps.

Asset URLs that change after export. Desk365-hosted CDN URLs can change if Desk365 migrates storage infrastructure. Download all assets during your initial extraction window, not in a deferred second pass days later.

Desk365 KB Export vs. Other Helpdesks

Platform Native KB Export API KB Export Export Format API Rate Limit (mid-tier plan)
Desk365 No Yes (v3) JSON (HTML + plain text body) 50 req/min (Plus, $22/user/mo)
Zendesk Guide No (use API) Yes JSON (HTML body only) 400 req/min (Suite Professional) — Zendesk rate limit docs
Freshdesk Partial (metadata only) Yes JSON 400 req/min (Estate) — Freshdesk rate limit docs
Zoho Desk Data Backup (full zip) Yes CSV + JSON 100 req/min (Professional)
HappyFox CSV export (metadata) Yes CSV / JSON Varies by plan

Desk365's KB export story is broadly comparable to Zendesk and Freshdesk — API-only for full content, JSON format, HTML bodies. The meaningful differences:

Rate limits: Desk365's Plus/Premium at 50 requests/minute is significantly more restrictive than Zendesk's 400/minute or Freshdesk's 400/minute on equivalent mid-tier plans. For large knowledge bases (500+ articles), this translates to real extraction time differences. A 500-article KB takes under 2 minutes on Zendesk's API; the same extraction on Desk365 Plus takes approximately 10–12 minutes with per-request overhead.

Dual content format: Desk365 returns both article_content (HTML) and article_content_text (plain text) in a single API response. Zendesk returns HTML only and requires client-side stripping for plain text. Freshdesk splits metadata export and content export into separate tooling. Desk365's approach reduces the number of API calls needed for content extraction.

Visibility granularity: Desk365 returns enumerated visibility codes (1–4 for portal, 1–2 for agent) with associated company and group lists. Zendesk Guide's user segments require separate API calls to resolve. This makes Desk365's exported access-control data more self-contained, but the mapping to target platforms is still manual.

For comparison guides on other platforms:

When the API Isn't Enough: Requesting a Data Dump

For large knowledge bases (1,000+ articles) on the Standard plan, the API rate limit (100 calls/hour) makes full extraction take 10+ hours of wall-clock time. In these cases:

  1. Contact Desk365 support at help@desk365.io and request a full data export of your KB content.
  2. Specify what you need: articles, categories, folders, attachments, and — if possible — version history.
  3. Ask about format: JSON or CSV, and whether attachments come as files or as download links.

This is especially relevant if you are ending your Desk365 subscription. GDPR Article 20 (right to data portability) and equivalent regulations support your right to receive your data in a structured, machine-readable format. Desk365 support is generally responsive to export requests from departing customers.

Making Desk365 KB Data Migration-Ready

Extracting the data is step one. Making it importable is step two. Migration-ready KB data requires these transformations, in order:

  1. HTML cleanup — Strip Desk365-specific CSS classes, fix broken tags, remove empty <p> and <div> wrappers, normalize whitespace. Use bleach (Python) or sanitize-html (Node.js).
  2. Image re-hosting — Download all inline images, upload to your target platform or a neutral CDN, rewrite src URLs in article_content HTML.
  3. Category/folder mapping — Map the Desk365 three-level hierarchy (Category > Folder > Article) to your target's structure. Zendesk uses Categories > Sections > Articles. Freshdesk uses Categories > Folders > Articles. Notion uses flat databases. Identify the target's hierarchy before import, not during.
  4. Visibility translation — Map Desk365's numeric visibility codes to your target's access model using the table in the Visibility section above. Capture unmappable rules in a sidecar CSV.
  5. Author mapping — Build a source-email → target-user-ID lookup table before running the import. Missing authors default to admin; that default destroys attribution silently.
  6. Status mapping — Filter or tag draft vs. published articles. Do not blindly import everything as Published.
  7. Internal link rewriting — After the initial import, extract new article URLs from the target, build an old-URL-to-new-URL map, and run search-and-replace on all article_content HTML before the final import pass.
  8. URL redirect plan — Publish 301 redirects from old Desk365 URLs to new URLs at your proxy or DNS layer before go-live.

For a full pre-migration checklist, see The Ultimate Knowledge Base Migration Checklist.

Frequently Asked Questions

Does Desk365 have a native knowledge base export feature?
No. Desk365's native export under Settings > Admin > Exports covers tickets, contacts, and companies but does not include knowledge base articles, categories, or folders. You must use the REST API v3 to extract KB data.
What format does the Desk365 KB API return?
JSON. Article content is provided as both HTML (article_content) and plain text (article_content_text). There is no native CSV export for KB data.
What are the Desk365 API rate limits for KB extraction?
Standard plan: 100 API calls per hour. Plus and Premium plans: 50 API calls per minute. The Standard plan's hourly cap makes large KB extractions significantly slower — a 500-article export with hierarchy calls can take several hours.
Does the Desk365 API export KB article attachments?
Partially. The API returns a has_attachments boolean flag per article but does not provide direct download URLs for attachment files. You need to parse the article HTML for inline image and file URLs and download them separately.
Can I export draft and archived knowledge base articles from Desk365?
The API returns both draft (status 0) and published (status 1) articles. Filter on the status field if you only need published content. Version history and deleted/trashed articles are not exposed through the API — recover trashed articles in the UI before export if needed.

More from our Blog

Desk365 to Intercom Migration: A Technical Guide
Intercom/Migration Guide/Help Desk

Desk365 to Intercom Migration: A Technical Guide

Technical guide to migrating from Desk365 to Intercom. Covers data model mapping, API extraction, ticket import, attachments, knowledge base, and validation.

Wahab Wahab · · 22 min read