---
title: "Salesforce Knowledge to Slack Canvas: API Limits & Data Mapping"
slug: salesforce-knowledge-to-slack-canvas-api-limits-data-mapping
date: 2026-09-30
author: Raajshekhar Rajan
categories: [Salesforce Knowledge, Slack Canvas, Migration Guide]
excerpt: "Salesforce Knowledge to Slack Canvas has no native path despite shared ownership. Data category visibility, versioning, merge fields, and API rate limits make this a complex migration."
tldr: "Treat Salesforce Knowledge to Slack Canvas as a visibility redesign, not a copy job: migrate published articles only, remap data categories to channels, re-host files, and plan for 2–4 hours of API runtime per 500 articles."
canonical: https://clonepartner.com/blog/salesforce-knowledge-to-slack-canvas-api-limits-data-mapping
---

# Salesforce Knowledge to Slack Canvas: API Limits & Data Mapping


# Salesforce Knowledge to Slack Canvas: API Limits & Data Mapping

There is no native migration path from Salesforce Knowledge to Slack Canvas. Salesforce acquired Slack in 2021 for $27.7 billion, and as of late 2026, ships an official Quip → Slack Canvas conversion path — but no built-in connector bridges Knowledge articles to canvases. ([help.salesforce.com](https://help.salesforce.com/s/articleView?id=platform.create_a_slack_canvas.htm&language=en_US&type=5)) Every article must be extracted via the Salesforce API, transformed to markdown, and loaded through the Slack Canvas API, with a manual redesign of your entire visibility model in between.

The hard part is not the content. It is mapping data category visibility to Slack channel membership, because the two access models have nothing in common.

If you are exploring Slack canvases as a destination for other document types, our [Quip to Slack Canvases migration guide](https://clonepartner.com/blog/blog/quip-to-slack-canvases-migration-the-official-salesforce-path) covers Salesforce's official in-product conversion flow. For broader knowledge base migration planning, start with our [migration checklist](https://clonepartner.com/blog/blog/the-ultimate-knowledge-base-migration-checklist-a-zero-downtime-plan).

## Required OAuth scopes and API credentials

Before writing a single line of migration code, you need credentials on both sides. This is the most common first blocker.

**Salesforce side — Connected App setup:**

Your Salesforce Connected App requires the following OAuth scopes:

| Scope | Purpose |
|---|---|
| `api` | General REST API and SOQL access |
| `bulk_api` | Bulk API 2.0 query jobs |
| `content` | ContentVersion binary download via the Files REST endpoint |
| `full` | Required if extracting via Tooling or Metadata API for field schema |

The integration user running extraction queries must have a profile or permission set that grants:
- **View All Data** (or equivalent field-level read access on `Knowledge__kav`)
- **Manage Categories** (to read the full `DataCategoryGroup` taxonomy, not just categories visible to their role)
- **Download Attachments** on the content objects

If the extraction user cannot see all categories, the `DataCategorySelection` query returns only the categories accessible to that user's role — and your mapping file is silently incomplete from the start.

**Slack side — required OAuth scopes:**

| Scope | API method(s) covered |
|---|---|
| `canvases:write` | `canvases.create`, `canvases.edit`, `canvases.access.set` |
| `canvases:read` | `canvases.sections.lookup` |
| `files:write` | `files.getUploadURLExternal`, `files.completeUploadExternal` |
| `channels:manage` | Creating and configuring private channels for access mapping |
| `groups:write` | Managing private channel membership |
| `users:read` | Resolving user IDs for `canvases.access.set` by-user sharing |

Install your Slack app at the workspace level (not user token). User tokens expire and are not appropriate for batch migration jobs running over hours.

## Why data category visibility is the hardest part

**Data categories** in Salesforce Knowledge are hierarchical labels organized into **DataCategoryGroups** that control both article classification and article visibility. An article tagged with categories from multiple groups is visible to a user only if that user has access to at least one category in **every** group applied to the article. Visibility is configured through three mechanisms — roles, permission sets, and profiles — and Salesforce evaluates them with a logical OR within each group. ([help.salesforce.com](https://help.salesforce.com/s/articleView?id=category_visibility_whatis.htm&language=en_US&type=5))

Salesforce enforces specific structural limits on categories: up to **5 category groups** with **3 active at a time by default**, **5 hierarchy levels** per group, **100 categories** per group, and up to **8 categories from one group on an article**. The API surface reflects this model: `Knowledge__DataCategorySelection` exposes article categorization, and the REST data-category resources return only the categories visible to the current user. ([help.salesforce.com](https://help.salesforce.com/s/articleView?id=category_whatis.htm&language=en_US&type=5))

Slack Canvas has no equivalent concept. Canvas access is controlled by **channel membership** and explicit sharing. The [`canvases.access.set` API method](https://clonepartner.com/blog/blog/slack-canvas-access-after-migration-canvasesaccessset-guide) accepts either `channel_ids` or `user_ids` — never both in the same call — with a maximum of **20 IDs per call**. It rejects DM and MPDM channel IDs entirely. If you share a canvas in a public channel, Slack warns that the canvas can become visible across the workspace or Enterprise org even when general access is otherwise limited. ([api.slack.com](https://api.slack.com/methods/canvases.access.set))

This means a category visibility rule like "agents with the EMEA role can see articles tagged *Geography > Europe* AND *Product > Enterprise*" has no direct expression in Slack. You must redesign that rule as a channel: create a `#kb-emea-enterprise` channel, populate it with the right members, and share the canvas there. If a category combination maps to more than 20 channels, your script must paginate the `canvases.access.set` requests to avoid HTTP 400 errors.

One naming trap worth flagging: Salesforce **audience channels** (Internal App, Customer, Partner, Public Knowledge Base) are publication targets. Slack **channels** are access containers. Same word, different model. ([developer.salesforce.com](https://developer.salesforce.com/docs/service/salesforce-knowledge-dev-guide/guide/knowledge-development-object-managing-articles.html))

**Effective audience** — a derived concept used throughout this guide — means the set of users who can access a specific article given its category tags and the org's role/profile/permission-set visibility configuration. You must compute this explicitly; Salesforce does not expose it as a single query result.

To extract an article's categories, your SOQL query must traverse the `DataCategorySelection` relationship:

```sql
SELECT Id, Title,
       (SELECT DataCategoryName, DataCategoryGroupName FROM DataCategorySelections)
FROM Knowledge__kav
WHERE PublishStatus = 'Online'
```

| Salesforce Knowledge concept | Slack Canvas reality | Migration action |
|---|---|---|
| Data category tree | No equivalent ACL tree | Build an explicit channel map |
| Role/profile/permission-set visibility | Channel membership or invited users | Maintain entitlements outside Slack, then apply sharing |
| Internal/Customer/Partner/Public audience channels | Public/private channels plus invited users | Reduce scope to internal Slack use cases first |
| Category-group intersection (AND logic) | No intersection logic | Collapse intersection to a single purpose-built channel |

### How to build the category-to-channel map

1. **Export your DataCategoryGroup hierarchy** via the Metadata API or Setup UI. List every category group and its child categories.
2. **Export role/profile/permission-set visibility assignments** for each category group. This tells you which users can see which category combinations.
3. **Identify the effective audience** for each article by cross-referencing its category tags against the visibility rules. Articles tagged across multiple groups will have audiences defined by the intersection of group-level visibility rules.
4. **Design Slack channels** that mirror those audiences. In practice, most orgs can collapse hundreds of category combinations into 10–30 channels — but this is a human judgment call, not an automated mapping.
5. **Batch the `canvases.access.set` calls.** With a 20-channel-ID limit per call, sharing a canvas to 50 channels requires three API calls per canvas. Budget accordingly.

> [!TIP]
> Treat the category redesign as a separate deliverable. Build a matrix with columns for **record type**, **data category path**, **old audience channel**, **new Slack channel(s)**, **exception users**, and **owner**. If that sheet is wrong, the migration is wrong.

### Standalone canvases vs. channel canvases

Slack allows only **one channel canvas per channel**, and access to that canvas is tied to channel membership. For article libraries, the more workable pattern is **standalone canvases** with default access set to **Invite only**, then shared into the specific private channels that replace each category slice. Standalone canvases require a paid Slack plan. ([api.slack.com](https://api.slack.com/methods/conversations.canvases.create))

## What happens to article versioning?

Salesforce Knowledge maintains a full publishing lifecycle per article. Each `Knowledge__kav` record (the article version object) carries one of three statuses: **Draft**, **Online** (published), or **Archived**. Every time a published article is edited, a new draft version is created with a distinct version number and its own record ID. The draft does not replace the published version until it goes through an approval workflow. The system stores up to ten versions by default, plus any versions attached to cases.

A Slack canvas has **one current body** and no version model accessible via the API. There is no draft state, no archive state, and no programmatic version history. The `canvases.edit` method overwrites content in place. Slack does expose revision history in the product UI, and admins can allow restoration of prior revisions — but the API model is centered on a single current body. ([slack.com](https://slack.com/help/articles/33536064287891-Manage-canvas-settings-in-Slack))

**Only the published (`Online`) version of each article should be migrated.** Draft articles are incomplete by definition. Articles pending approval — those that have been submitted to a workflow but not yet approved — are also not `Online` and should be treated as drafts. If you have a regulatory or audit requirement to preserve version history, export it to a separate archive (a database, S3 bucket, or CSV export from the Knowledge Audit Trail) before migrating the published content to Canvas. Canvases cannot satisfy a version-history compliance requirement.

```sql
SELECT Id, KnowledgeArticleId, Title, UrlName, ArticleNumber,
       PublishStatus, VersionNumber, Language
FROM Knowledge__kav
WHERE PublishStatus = 'Online'
  AND Language = 'en_US'
```

Keep the original `KnowledgeArticleId`, article number, and old URL in your migration ledger so you can trace every canvas back to its source record.

### Multilingual Knowledge articles

The `Language = 'en_US'` filter above is illustrative. Most enterprise Knowledge instances contain articles in multiple locales — Salesforce supports translations stored as separate `Knowledge__kav` records with the same `KnowledgeArticleId` but different `Language` values.

Your migration must decide: migrate one locale per canvas, or consolidate translations into a single canvas with language sections. The API supports either, but the access model implications differ:

- **One canvas per locale:** Simpler content structure, but doubles or triples canvas count and `canvases.access.set` calls. Channel membership must be replicated per locale.
- **Consolidated canvas:** Reduces canvas sprawl, but requires section-level language labeling and makes content harder to maintain post-migration.

To enumerate all language variants for your Knowledge instance:

```sql
SELECT Language, COUNT(Id) articleCount
FROM Knowledge__kav
WHERE PublishStatus = 'Online'
GROUP BY Language
ORDER BY COUNT(Id) DESC
```

Run this before designing your channel map. If you have 12 locales and 800 articles, you potentially face 9,600 canvases under a one-per-locale model — which changes your throughput math significantly.

## Rich text fields, merge fields, and markdown conversion

Knowledge article bodies are stored in rich text fields on the `Knowledge__kav` object. These fields contain HTML — but not clean, portable HTML. Two problems arise during migration.

**Salesforce merge fields.** Rich text fields can contain merge field syntax like `{!Account.Name}` or `{!Case.CaseNumber}` that resolve dynamically inside the Salesforce org. Outside the org, they resolve to nothing. If you migrate them as-is, they appear as broken bracketed text inside your canvases. Your migration script must detect these patterns (regex for `\{!.*?\}` works as a starting point) and either:

- Replace them with static placeholder text (e.g., `[Account Name]`)
- Strip them entirely
- Flag the article for manual review

**Slack Canvas markdown limitations.** The Canvas API accepts content as a `document_content` object with `type: "markdown"`. Supported formatting includes headings, bold, italic, links, code blocks, blockquotes, and lists — but not arbitrary HTML. Tables, colored text, custom CSS, embedded Visualforce components, and Block Kit elements will not survive. You need an HTML-to-markdown conversion step, and you should expect lossy output for any article that uses advanced formatting. ([help.salesforce.com](https://help.salesforce.com/s/articleView?id=fields_using_rich_text_area.htm&language=en_US&type=5))

**Canvas content size limit.** The `document_content` object in a `canvases.create` or `canvases.edit` call is subject to a maximum payload size of approximately **1 MiB** per request, based on observed API behavior (Slack does not publish this limit prominently in their public documentation). Most Knowledge articles fall well under this limit, but long-form troubleshooting guides with embedded images can approach it. Monitor response sizes during development and implement a split-or-truncate step for any article body that exceeds 900 KB after conversion.

**Knowledge search synonym groups and promoted search terms** defined in your Salesforce org are lost in this migration. There is no Slack Canvas equivalent. If [findability within Slack](https://clonepartner.com/blog/blog/naming-indexing-10000-slack-canvases-after-migration) is a post-migration concern, document your synonym groups before migrating and plan to configure equivalent terms in whatever enterprise search layer indexes your workspace.

The overall conversion pipeline:

```text
extract HTML
→ sanitize unsupported markup
→ resolve or remove Salesforce-specific tokens
→ download media and files
→ upload media to Slack
→ rewrite internal article links
→ convert to Slack markdown
→ split or truncate if body approaches 1 MiB
→ create canvas with the final body
```

**Section-level structure.** The `canvases.sections.lookup` API method allows you to retrieve section IDs within an existing canvas, which is required if you later need to update individual sections via `canvases.edit` rather than replacing the entire body. For initial load, create canvases with the full content in the `canvases.create` call. For large articles that require post-migration updates, store section IDs from `canvases.sections.lookup` responses in your migration ledger alongside the canvas ID.

Create canvases with the bulk of the content in the initial `canvases.create` call when possible. Because `canvases.edit` supports only one operation per call, section-by-section patching is slower and harder to retry cleanly.

## Custom article types mean per-tenant field mapping

Field mapping is per-tenant because **Salesforce Knowledge does not have a universal article schema across orgs**. In Lightning Knowledge, article structure lives on `Knowledge__kav` and is differentiated with **record types**. In Salesforce Classic, custom article types created separate objects like `FAQ__kav` or `Procedure__kav`. Lightning record types replaced these custom article types, so modern orgs converge on one object but still keep locally defined record types, layouts, and custom fields. ([developer.salesforce.com](https://developer.salesforce.com/docs/service/salesforce-knowledge-dev-guide/guide/knowledge-development-object-managing-articles.html))

One org might store article bodies in a field called `Article_Body__c`. Another uses `Resolution__c` and `Symptom__c` as separate rich text fields. A third has `Steps_to_Reproduce__c`, `Root_Cause__c`, and `Workaround__c` — each needing to be concatenated into a single canvas body.

Before writing migration code, you must:

1. Run a `DESCRIBE` call on `Knowledge__kav` to enumerate all custom fields
2. Identify which fields contain article content vs. metadata
3. Decide how to flatten multiple rich text fields into a single markdown document
4. Handle org-specific custom fields that carry structured data (picklists, lookups, formulas)

A workable canvas template:

- **Canvas title:** article title
- **Header metadata:** record type, owner, last review date, legacy article number
- **Body sections:** summary, steps, details, resolution, notes
- **Footer:** source article ID, old URL, redirect target, migration timestamp

## How to migrate Knowledge article attachments

Salesforce Knowledge articles store attachments as **ContentVersion** records linked through the **ContentDocumentLink** junction object. To extract them, query `ContentDocumentLink` where `LinkedEntityId` matches the article's `KnowledgeArticleId`, then fetch the `VersionData` blob from the corresponding `ContentVersion` record. Note that SOQL on `ContentDocumentLink` requires filtering on `Id`, `ContentDocumentId`, or `LinkedEntityId`. ([developer.salesforce.com](https://developer.salesforce.com/docs/platform/mobile-offline/guide/use-images-upload-file-representation.html))

You cannot copy image URLs from the Salesforce HTML body and paste them into Slack. Those URLs are authenticated endpoints tied to active Salesforce sessions. Anyone not logged into Salesforce will see broken images.

Uploading to Slack requires the newer external upload sequence. Slack deprecated `files.upload` and sunset it on **November 12, 2025**. The current flow: ([docs.slack.dev](https://docs.slack.dev/reference/methods/files.getUploadURLExternal/))

1. **Query relationships:** Query `ContentDocumentLink` for each article to retrieve associated `ContentVersion` IDs.
2. **Download binary data:** Download the file payload via the Salesforce REST API (`/sfc/servlet.shepherd/version/download/<ContentVersionId>`).
3. **Request Slack upload URL:** Call `files.getUploadURLExternal` with the filename and byte length.
4. **POST the binary** to the returned upload URL.
5. **Complete upload:** Call `files.completeUploadExternal` to finalize the file in Slack.
6. **Rewrite HTML tags:** Parse the Salesforce article body, locate the original `<img>` tags, and replace `src` attributes with the new Slack file URLs.

One important caveat: **you cannot reliably embed a Slack-hosted file directly into a canvas body via the API.** Canvas markdown supports images via URL, but Slack's internal file URLs are not stable external links. The realistic approach is to attach files to the same channel where the canvas lives and reference them with a link in the canvas content.

For a deeper dive on attachment migration patterns, see our guide on [migrating images, attachments, and embeds without broken links](https://clonepartner.com/blog/blog/how-to-migrate-images-attachments-embeds-without-broken-links).

## Article URLs change — plan for redirects

Salesforce Knowledge article URLs differ between Classic and Lightning. In Lightning, the URL contains the Knowledge Article Version ID. In Classic, it uses the Knowledge Article ID. Public-facing articles served through Experience Cloud or Salesforce Sites use yet another URL pattern based on `UrlName`.

Slack canvases have **no public URL**. They are accessible only within the Slack workspace to users who have been granted access. This creates three problems:

- **External links break.** Any URLs indexed by search engines, bookmarked by customers, or embedded in case records will return 404s once you deprecate Knowledge.
- **You need 301 redirects** if the Knowledge articles were publicly accessible. Because Slack Canvas cannot host redirects, you must stand up an external redirect gateway — a Cloudflare Worker, Nginx reverse proxy, or similar — to intercept requests to legacy Salesforce URLs and forward them to wherever the canonical content now lives.
- **Internal Salesforce links** (between articles, or from Cases to attached articles) will not resolve in Slack. You need a lookup table so macros, bookmarks, chatbot answers, and case templates can find the new canvas.

If your Knowledge base serves both internal agents and external customers, Canvas only covers the internal use case. The external-facing content needs a different destination entirely.

## API throughput: Bulk API and Slack rate limits

The real throughput constraint is the combination of Salesforce query limits and Slack's per-method rate tiers.

**Salesforce side:**

- **Bulk API 2.0** is recommended for operations over 2,000 records. Bulk API 2.0 query jobs **do not consume batches** from the rolling 15,000-batch daily allocation — they have their own daily ceilings, including **10,000 query jobs** and **1 TB** of query result storage per 24-hour window. Classic Bulk API PK chunking does count toward the batch limit. ([developer.salesforce.com](https://developer.salesforce.com/docs/platform/salesforce-app-limits-cheatsheet/guide/salesforce-app-limits-platform-bulkapi.html))
- The typical bottleneck is **attachment downloads**, which are individual REST API calls per `ContentVersion` record and count against your org's daily API call allocation.

**Slack side:**

| Operation | API method | Rate tier | Effective throughput |
|---|---|---|---|
| Create canvas | `canvases.create` | Tier 2 | ~20/min |
| Set access | `canvases.access.set` | Tier 3 | ~50/min |
| Edit content | `canvases.edit` | Tier 3 | ~50/min |
| Lookup sections | `canvases.sections.lookup` | Tier 3 | ~50/min |
| Upload file (step 1) | `files.getUploadURLExternal` | Tier 4 | ~100/min |
| Upload file (step 2) | `files.completeUploadExternal` | Tier 4 | ~100/min |

**Runtime estimate — explicit assumptions:**

For a Knowledge base with **500 articles**, **average body size 15 KB**, **0.4 attachments per article** (200 total files), **5% retry rate**, running sequentially with exponential backoff:

- Canvas creation: 500 articles ÷ 20/min = **25 minutes minimum**
- Access setting (assume avg 3 channels per article, 1 call each): 500 calls ÷ 50/min = **10 minutes**
- Attachment upload (200 files × 2 calls each): 400 calls ÷ 100/min = **4 minutes**
- Retries at 5% add ~10% to total runtime
- **Total API runtime: approximately 45–60 minutes** for 500 articles at these parameters

Scale linearly: 5,000 articles with the same profile = 7–10 hours of API runtime, not counting development, testing, the category-to-channel mapping work, or content transformation time. If your article count is in the thousands and includes multilingual variants, plan for a multi-day migration window.

Your migration script must implement **exponential backoff** and retry logic to handle `HTTP 429 Too Many Requests` responses.

## Idempotency and restart safety

Migration scripts fail. A run that processes 300 of 500 articles before hitting an unhandled error must be resumable without duplicating canvases or corrupting access grants.

**Minimum viable migration ledger** — write to a database or CSV after each successful API call:

| Column | Value | Purpose |
|---|---|---|
| `knowledge_article_id` | Salesforce KnowledgeArticleId | Source record identifier |
| `knowledge_version_id` | Knowledge__kav Id | Specific version extracted |
| `canvas_id` | Slack canvas ID from `canvases.create` response | Resume target |
| `access_set` | Boolean | Skip `canvases.access.set` if already completed |
| `attachments_uploaded` | JSON array of ContentVersion IDs | Skip re-upload |
| `status` | `pending` / `complete` / `failed` | Filter on restart |

On restart, filter `WHERE status != 'complete'` and skip any article where `canvas_id` is already populated — use `canvases.edit` to update content rather than creating a duplicate. Check `access_set` before re-issuing `canvases.access.set` calls, since Slack does not deduplicate access grants idempotently across repeated calls.

**Do not call `canvases.create` twice for the same article.** There is no unique-constraint enforcement on canvas creation. Two calls produce two canvases with no linkage between them.

## Step-by-step migration approach

### 1. Audit and export
- Query all `Knowledge__kav` records where `PublishStatus = 'Online'`
- Run the locale distribution query to enumerate all language variants requiring migration decisions
- Export `DataCategorySelection` records to capture category tags per article
- Export `ContentDocumentLink` and `ContentVersion` records for attachments
- Run `DESCRIBE` on `Knowledge__kav` to enumerate custom fields
- Inventory record types, languages, audience channels, and article counts
- Export Knowledge search synonym groups and promoted search terms for reference

### 2. Design the channel map
- Analyze category-group combinations and current visibility rules
- Map each effective audience to a Slack channel (create channels as needed)
- Validate that channel membership matches the intended audience
- Document exception users and ownership in the mapping matrix
- Confirm Slack app has `channels:manage` and `groups:write` scopes needed to create and populate channels programmatically

### 3. Transform content
- Convert rich text HTML to Slack-compatible markdown
- Strip or replace Salesforce merge fields
- Concatenate multi-field article bodies into a single markdown document
- Rewrite internal article links using the migration ledger lookup table
- Validate output is under the ~1 MiB canvas content threshold

### 4. Load into Slack
- Initialize migration ledger before first API call
- Create canvases via `canvases.create` with title and initial content; write `canvas_id` to ledger immediately
- Upload attachments via `files.getUploadURLExternal` + `files.completeUploadExternal`; record each uploaded file ID
- Set access via `canvases.access.set`, batching `channel_ids` in groups of 20
- Implement exponential backoff for 429 responses
- Mark each row `complete` in the ledger only after all steps succeed

### 5. Validate and redirect
- Spot-check content fidelity across article types and record types
- Verify access controls by testing with users from different audience segments
- Set up 301 redirects for any publicly-accessible article URLs
- Archive or tombstone the original Knowledge articles

## When Slack Canvas is the wrong destination

> [!WARNING]
> If your Salesforce Knowledge instance uses data categories primarily for agent-facing article visibility — where different support tiers see different articles based on role hierarchy — Slack Canvas is a poor target. Canvas was designed for collaborative documents, not gated knowledge delivery.

Slack Canvas lacks:

- **Cross-canvas search** — no unified search API that queries canvas content the way Salesforce Knowledge search works
- **Analytics** — no view counts, article ratings, or deflection metrics
- **Approval workflows** — no draft/review/publish cycle
- **Public access** — canvases are workspace-internal only
- **Version history via API** — no rollback, no audit trail
- **Search synonym management** — no equivalent to Salesforce Knowledge promoted search terms

**Feature comparison against alternative destinations:**

| Capability | Slack Canvas | Notion | Confluence | Guru |
|---|---|---|---|---|
| Role-based access control | Channel membership only | Workspace permissions + page-level | Space/page permissions | Card groups + permissions |
| Draft/review/publish workflow | None | Manual | Native | Native (verification workflow) |
| Public-facing content | No | Yes (public pages) | Yes (public spaces) | No |
| API version history | No | No (page history in UI only) | Yes | Yes |
| Full-text search across all content | Workspace search only | Yes | Yes | Yes |
| Analytics / view counts | No | No | Yes (premium) | Yes |

**Migration makes sense when:**

- You are moving lightweight internal reference docs (onboarding guides, process docs, runbooks) that do not need gated visibility
- Your team already lives in Slack and needs content where they work
- The Knowledge articles are a subset, not the entire knowledge base

**Migration is a poor fit for:**

- Agent KBs with category-based entitlements
- Customer-facing or SEO-sensitive help content
- Partner/community knowledge with external audience rules
- Content that depends on draft/review/archive workflows
- Large attachment-heavy libraries with stable public URLs
- Multilingual knowledge bases where locale management is operationally significant

**Decision rule:** If the primary consumer of your Knowledge articles is external (customers, partners, public web) or if the visibility model requires more than 30 distinct access groups, route the content to Confluence, Notion, or a dedicated knowledge base platform instead of Canvas. Reserve Canvas for the internal, collaborative, low-access-complexity subset.

> ClonePartner handles the field mapping, content transformation, and API orchestration for Knowledge migrations — to Canvas, Confluence, Notion, or wherever your content needs to go. Book a free 30-minute call to scope your project.
>
> [Talk to us](https://clonepartner.com/talk-to-us?duration=30&utm_source=blog&utm_medium=button&utm_campaign=demo_bookings&utm_content=cta_click&utm_term=demo_button_click)

## Frequently asked questions

### Is there a native Salesforce Knowledge to Slack Canvas migration tool?

No. Despite both products being owned by Salesforce, there is no built-in connector, export tool, or admin feature to move Knowledge articles into Slack Canvas. Salesforce ships an official Quip → Canvas conversion path, but nothing for Knowledge. You must extract articles via the Salesforce API, transform the content to markdown, and create canvases through the Slack Canvas API.

### How do Salesforce Knowledge data categories map to Slack Canvas permissions?

They do not map directly. Knowledge uses DataCategoryGroups with role/profile/permission-set visibility evaluated with a logical OR. Canvas access is controlled by channel membership or explicit user sharing via canvases.access.set, which accepts a maximum of 20 channel IDs or 20 user IDs per call. You must redesign category visibility rules as Slack channels.

### Does Slack Canvas support article versioning like Salesforce Knowledge?

No. Salesforce Knowledge maintains draft, published, and archived versions per article, each with its own record ID. A Slack canvas has one current body with no version model accessible via the API. Only the published (Online) version of each article should be migrated.

### What happens to Salesforce merge fields when moved to Slack?

Merge fields like {!Account.Name} resolve to nothing outside the Salesforce org. They appear as broken bracketed text in canvases. Your migration script must detect these patterns and either replace them with static placeholder text, strip them, or flag the article for manual review.

### How long does a Salesforce Knowledge to Slack Canvas migration take?

For 500 articles and 200 attachments, the API runtime alone takes 2–4 hours due to Slack's Tier 2 rate limit on canvases.create (~20 per minute). The category-to-channel mapping and per-tenant field mapping work can add days or weeks of planning before any code runs.
