---
title: "Slack Canvas to Document360 Migration: A Technical Guide"
slug: slack-canvas-to-document360-migration-a-technical-guide
date: 2026-10-01
author: Rishabh Makhar
categories: [Slack Canvas, Document360, Migration Guide]
excerpt: "How to move Slack Canvas content into Document360 without broken links, bad taxonomy, or publishing internal-only context to the public."
tldr: "Every Slack Canvas needs a rewrite before it becomes a Document360 article. @mentions, unfurls, and Slack-hosted images all break on publish. Design the category tree from channels and judgment — Canvas has no folder concept."
canonical: https://clonepartner.com/blog/slack-canvas-to-document360-migration-a-technical-guide
---

# Slack Canvas to Document360 Migration: A Technical Guide


**Migrating Slack Canvas content into Document360 is not a data conversion — it is an editorial project.** Canvases are internal documents written for people who already share context: they assume the reader knows the team, reference @mentions that resolve to Slack user IDs, embed channel links that go nowhere outside the workspace, and contain Slack-hosted images that require authentication to view. Moving them into a structured knowledge base means every canvas needs a rewrite pass before it becomes an article.

There is no native importer. Document360 has no Slack integration for pulling canvas content, and Slack has no Document360 export option. ([docs.document360.com](https://docs.document360.com/docs/slack)) The pipeline is: inventory canvases via the Slack API, extract markdown, rewrite for a public audience, design a category tree that Canvas never had, re-upload images, and push articles through Document360's API. This guide covers each step with the real constraints you will hit.

For a broader framework on knowledge base migrations, see [The Ultimate Knowledge Base Migration Checklist](https://clonepartner.com/blog/blog/the-ultimate-knowledge-base-migration-checklist-a-zero-downtime-plan).

| Feature | Slack Canvas | Document360 | Migration Action Required |
|---------|--------------|-------------|---------------------------|
| **Hierarchy** | Flat (tied to channels/DMs) | Strict (Category → Article) | Manual taxonomy design |
| **Headings** | H1 to H3 only | H1 to H6 supported | Restructure during rewrite |
| **Tables** | Max 300 cells, no formulas | Standard Markdown/HTML tables | Verify size; convert if targeting WYSIWYG |
| **Images** | Private Slack permalinks | Hosted in Document360 Drive | Download via token, re-upload |
| **Mentions** | Slack User IDs | Standard text | Regex replacement |
| **Checklists** | Interactive UI elements | No checklist widget | Convert to bullet/ordered lists |
| **Comments** | Threaded, tied to canvas UI | Not importable | Review for missing context; do not publish |
| **Tabs (post-Apr 2025)** | Multiple canvas tabs per channel | Single article per canvas | Each tab requires a separate article |

## Required Slack API Scopes and Document360 Permissions

Before writing a line of migration code, collect every credential you need. Missing one scope mid-run forces a token regeneration and a partial re-run.

| Requirement | Value | Why It Is Needed |
|---|---|---|
| Slack: `files:read` | Bot token scope | `files.list` inventory, file metadata |
| Slack: `canvases:read` | Bot token scope | `canvases.getContent` body retrieval |
| Slack: `users:read` | Bot token scope | `users.list` for mention ID-to-name mapping |
| Slack: `channels:read` | Bot token scope | Channel name lookup for category mapping |
| Document360: API key | Project-scoped | All article, category, and Drive endpoints |
| Document360: `project_version_id` | Retrieved via `GET /v2/ProjectVersions` | Required on every article creation call |

Add all scopes before installing the Slack app to a workspace. Slack does not allow adding scopes to an existing token without reinstalling.

## Why This Is a Rewrite Project, Not an Export

Slack canvases are written for an audience already inside the workspace. A canvas pinned to `#eng-onboarding` can say "ask @sarah" and everyone knows who Sarah is, or link to a thread in `#incidents` and assume the reader has access. The moment you publish that content to a Document360 knowledge base, every one of those assumptions breaks.

When you migrate between traditional knowledge bases — like moving from [Confluence to Document360](https://clonepartner.com/blog/blog/confluence-to-document360-migration-api-limits-data-mapping-guide) — the content is already structured as standalone articles. Slack Canvases are fundamentally different. They are written for a specific channel, assuming the reader has the full context of the surrounding conversations.

The specific failure modes:

- **@mentions** render as Slack user IDs (`<@U071CCRCVFH>`) in the exported markdown. Outside Slack, they mean nothing. Every mention must be replaced with a name, a role, or removed entirely.
- **Channel links** (`<#C073UAJRW4R>`) resolve to nothing for readers who are not in the workspace. References like "see the discussion in #platform-bugs" are dead ends.
- **Canvas and message unfurls** — canvases can embed previews of other canvases and Slack messages. These are Slack-internal rich previews that will not render anywhere else. When exported, they revert to bare URLs or Slack-internal embed references.
- **Slack-hosted images** use authenticated URLs (`url_private_download`) that return a sign-in page for anyone without a valid Slack session. ([docs.slack.dev](https://docs.slack.dev/reference/objects/file-object/))
- **Date formatting** — Slack uses a special timestamp format (`<!date^1392734382^{date_num}|2014-02-18>`) that must be parsed and replaced with human-readable dates.
- **Assumed context** — internal shorthand, project codenames, relative time references like "this week," and references to "the doc in the channel" need to be made explicit or cut.

This is not a quality-assurance pass you can skip. Publishing internal content without rewriting it creates a knowledge base full of broken references and insider jargon that confuses the people it is supposed to help.

Not every canvas should become an article. Slack positions canvases for project plans, onboarding, incident coordination, and meeting notes as much as formal knowledge capture. ([docs.slack.dev](https://docs.slack.dev/surfaces/canvases/)) Some of that material is working state, not reader-facing documentation. It should stay in Slack or be archived instead of polished into public docs.

A useful triage heuristic: a canvas is worth migrating if it answers a question a new reader — someone without workspace context — would actually ask. A canvas is not worth migrating if it is primarily a record of decisions made rather than guidance for decisions to be made.

## What Breaks in the Canvas Format Itself?

**Slack Canvas supports headings only from H1 through H3**, so the article structure you extract will be shallow. Document360 reserves H1 for the article title and supports H2 through H6 in the body. If your Document360 articles need deeper heading hierarchies, those must be added during the rewrite — they do not exist in the source material. ([docs.slack.dev](https://docs.slack.dev/surfaces/canvases/))

**Canvas tables are capped at 300 cells** in any combination of rows and columns, and they do not support formulas or computed values. They export as standard Markdown tables, which Document360 renders natively in Markdown article mode. If your canvases contain tables with calculations, those come through as static values — confirm the numbers are correct before publishing.

> [!WARNING]
> **Checklists will not survive.** Slack Canvas checklists are interactive elements tied to Slack's UI. Document360 has no checklist widget. Convert them to bullet lists or ordered steps during the rewrite.

> [!TIP]
> Use **Markdown articles** when the source is mostly text and tables. Document360's Advanced WYSIWYG editor does not render Markdown table syntax as a table, so if you target WYSIWYG or HTML articles, convert Slack tables to HTML first. ([docs.document360.com](https://docs.document360.com/docs/basic-markdown-syntax))

The Canvas API represents content as markdown through the `document_content` object. Supported formatting includes bold, italic, strikethrough, bulleted and ordered lists, checklists, code blocks, quotes, dividers, links, tables, and @mentions — but no images as inline data. Images are referenced by Slack-internal URLs.

**Canvas comments are not returned by `canvases.getContent`.** The API returns only the canvas body — the threaded comment layer visible in the Slack UI is a separate data structure and is not included in the content response. If comments contain clarifications or corrections that are not reflected in the body, you must retrieve those separately via the conversations API or capture them manually before migration. Do not assume the exported body is the complete record.

> [!NOTE]
> **April 2025 tab change:** Slack began converting channel and DM canvases into multi-tab canvases on **April 9, 2025**. Each tab is a discrete canvas with its own canvas ID. `canvases.getContent` returns the content of a single tab — not all tabs in a channel canvas. If a channel canvas has three tabs, you need three separate `canvases.getContent` calls with three different canvas IDs. Audit current canvas tab structure before assuming a one-to-one relationship between channel canvases and articles. ([slack.com](https://slack.com/help/articles/21290478840979-Feature-change-notice--Channel-canvases))

## How Do You Inventory All Canvases in a Slack Workspace?

Slack does not have a `canvases.list` method. To get an inventory of all canvases—a constraint we also hit when [migrating Slack Canvas to Notion](https://clonepartner.com/blog/blog/slack-canvas-to-notion-migration-api-limits-data-mapping)—use `files.list` filtered to type `canvas`. ([docs.slack.dev](https://docs.slack.dev/surfaces/canvases/))

```python
import time
from slack_sdk import WebClient

client = WebClient(token="xoxb-your-bot-token")
canvases = []
page = 1

while True:
    resp = client.files_list(types="canvas", count=100, page=page)
    files = resp["files"]
    if not files:
        break
    canvases.extend(files)
    page += 1
    time.sleep(1.5)  # Tier 3: ~50 req/min, be conservative

print(f"Found {len(canvases)} canvases")
```

The `files.list` endpoint is rate-limited at **Tier 3 (~50 requests per minute)**. Each response includes a `paging` object with `total` and `pages` fields. You can filter by `channel` to scope the inventory to a specific channel, which is useful for building the taxonomy later. Extraction requires the `files:read` scope for inventory and `canvases:read` for content retrieval. ([api.slack.com](https://api.slack.com/methods/files.list))

To extract the actual content of each canvas, use `canvases.getContent`, which returns the full canvas as markdown (default) or HTML. The entire canvas comes back in a single `content` string with no pagination.

```python
for canvas in canvases:
    content = client.canvases_getContent(
        canvas_id=canvas["id"],
        content_type="markdown"
    )
    markdown_body = content["content"]
    # Store alongside metadata: title, channel, created, updated
```

> [!NOTE]
> The markdown returned by `canvases.getContent` is capped at **1 MiB (1,048,576 characters)** per canvas. Most internal docs fall well under this limit, but sprawling canvases used as wikis may hit it. If a canvas is truncated at the 1 MiB boundary, the response does not include a truncation warning — the content simply ends. Validate completeness by checking for structural markers like closing headings or list items that appear to terminate mid-document.

## Building the Category Tree from Channels

**Document360 organizes content as Projects → Workspaces → Categories → Articles.** A canvas carries none of this structure. There is no folder concept in Slack Canvas — a canvas either belongs to a channel or exists as a standalone document. The taxonomy for your Document360 knowledge base has to be designed, not derived.

Three signals to work from:

1. **Channel names and purposes.** If your canvases are concentrated in channels like `#product-docs`, `#api-reference`, and `#support-playbooks`, those channel names often map naturally to top-level Document360 categories. A channel like `#refunds` might become a Folder category called **Billing and Refunds**.
2. **Index canvases.** Many teams create a "master" canvas in a channel that links to other canvases — a table of contents. These index canvases reveal the team's intended grouping, even though Slack never enforced it as a hierarchy.
3. **Judgment.** Some canvases will not fit any channel-based grouping. Meeting notes, one-off guides, and ad-hoc docs need a human decision about where they belong — or whether they belong at all.

Document360 supports up to **seven levels of category nesting**, but their own best practices recommend staying within two levels of subcategories. Category types include **Folder** (navigation-only), **Index** (has a slug and SEO settings), and **Page** (full article functionality at the category level). ([docs.document360.com](https://docs.document360.com/docs/category-types))

Do not fake languages with categories named "FR" or "DE" — Document360 already has first-class language support inside each workspace. A versioned or audience-specific channel may be a better fit for a separate workspace than a deeply nested category. ([docs.document360.com](https://docs.document360.com/docs/workspaces-languages))

Plan the tree before writing a single API call. Create the categories in Document360 first, capture their IDs, then use those IDs when creating articles. Document360 requires a `category_id` for every article — if you do not map this in advance, you cannot automate the upload.

### Generating Article Slugs

Document360 can auto-generate a slug from the article title on creation, but **title changes do not later update the slug**. Changing a published slug requires redirect rules. If your migration team uses temporary titles on import and fixes them later, you create avoidable redirect work. ([docs.document360.com](https://docs.document360.com/docs/article-redirect-rules))

Slack allows multiple canvases with the exact same title, so your migration script must generate unique slugs. Appending a short fragment of the Slack file ID prevents collisions:

```python
import re

def generate_doc360_slug(title, file_id):
    slug = title.lower()
    slug = re.sub(r'\s+', '-', slug)
    slug = re.sub(r'[^a-z0-9\-]', '', slug)
    return f"{slug}-{file_id[:4].lower()}"
```

## Rewriting Slack Markdown for Document360

Slack's flavor of Markdown contains proprietary syntax that Document360 will not understand. Before pushing content to the API, run a translation pass.

**User Mentions:** Find `<@U [A-Z0-9]+>` and replace with the user's actual name. Build a local map of Slack User IDs to display names using the `users.list` API before starting the rewrite loop — this avoids one API call per mention per canvas.

**Channel Links:** Find `<#C [A-Z0-9]+\|channel-name>` and replace with standard text. If the channel corresponds to a new Document360 category, rewrite it as a Markdown link pointing to the new Document360 URL.

**Date Formatting:** Slack uses a special timestamp format: `<!date^1392734382^{date_num}|2014-02-18>`. Parse this and replace it with a human-readable date string. The fallback text after the pipe character is a reliable source if you do not want to convert Unix timestamps.

**Unfurls:** Rich preview cards revert to bare URLs or Slack-internal embed references. Replace with standard links or screenshots where appropriate.

**Multi-column layout:** Slack canvases support column layouts that have no equivalent in Document360's article format. Collapse columns into a single reading order instead of trying to preserve Slack layout.

**What Document360 returns for invalid markdown:** If the `content` field contains syntax that Document360 cannot parse, the API accepts the article but renders the raw syntax as visible text rather than rejecting the request. There is no parse error in the API response. This means a broken markdown table or an unresolved Slack syntax fragment will silently appear as garbled text in the published article. Validate rendered output post-import, not just API response codes.

## How Do You Handle Images and File Attachments?

Slack Canvas images are stored behind authenticated URLs. The `url_private_download` field points to the image, but fetching it requires a valid Slack token. Anyone without a Slack session — meaning every reader of your public knowledge base — sees a sign-in page instead of the image. ([docs.slack.dev](https://docs.slack.dev/reference/objects/file-object/))

The migration path:

1. **Parse the markdown** for all image URLs matching `https://files.slack.com/files-pri/...`
2. **Download each image** using your Slack bot token in the Authorization header.
3. **Upload to Document360 Drive**, which gives every file a permanent CDN URL in the format `https://cdn.document360.io/[project-id]/Images/Documentation/[filename]`.
4. **Rewrite the image references** in the markdown body to point to the new Drive URLs.

Document360's Drive keeps CDN URLs stable even when files are moved between folders, so early folder choices do not have to be perfect. ([docs.document360.com](https://docs.document360.com/docs/add-a-file))

Slack Canvases often contain embedded PDFs or CSVs, represented as links to other Slack files. These must be downloaded via the same Bearer token method, uploaded to Document360 Drive, and the markdown links updated. If you skip this, users clicking a PDF link in Document360 get redirected to a Slack login page.

**Document360's v3 API includes Drive management endpoints** that support programmatic file upload. If you are on the v2 API or on a plan that does not expose Drive endpoints, images must be uploaded manually through the portal — a serious bottleneck for canvas libraries with dozens of images per document. Confirm Drive API access against your specific plan before building the automation. Check `POST /v3/drive/files` in the v3 API reference for current endpoint availability.

For a deeper look at image migration patterns, see [How to Migrate Images, Attachments & Embeds Without Broken Links](https://clonepartner.com/blog/blog/how-to-migrate-images-attachments-embeds-without-broken-links).

## Pushing Articles to the Document360 API

Document360's article creation endpoint is `POST /v2/Articles`. It accepts a `content_type` parameter: `0` for Markdown, `1` for WYSIWYG (HTML), `2` for Advanced WYSIWYG. Since canvas content is already markdown, `content_type: 0` is the natural fit.

```json
{
  "title": "Getting Started with the Platform API",
  "category_id": "8dfb5c7e-fcbe-4797-b144-1a7ca2508f50",
  "project_version_id": "rffb5c7e-fcbe-4797-b144-1a7ca2508fvew",
  "user_id": "team-account-id",
  "content": "# Getting Started\n\nThis guide walks you through...",
  "content_type": 0,
  "order": 0
}
```

Key mapping decisions:

| Canvas Property | Document360 Field | Notes |
|---|---|---|
| `file.title` | `title` | Review for public readability — internal titles like "Q3 runbook v2 FINAL" need editing |
| Canvas body (markdown) | `content` | After the rewrite pass, not raw |
| Channel association | `category_id` | Manually mapped from your planned category tree |
| N/A | `slug` | Auto-generated from title; override to control URLs |
| N/A | `project_version_id` | Required — get via `GET /v2/ProjectVersions` |
| N/A | Language | Default language is set per workspace; multilingual requires separate article versions |

**Common API error responses to handle explicitly:**

| HTTP Status | Condition | Resolution |
|---|---|---|
| `400 Bad Request` | Invalid `category_id` or missing required field | Verify category IDs were captured after creation, not before |
| `409 Conflict` | Duplicate slug within a category | Use the file-ID suffix slug generation; do not rely on auto-generated slugs |
| `429 Too Many Requests` | Rate limit exceeded | Implement exponential backoff; Document360 does **not** return a `Retry-After` header |
| `200 OK` with garbled body | Invalid markdown accepted silently | Validate rendered content post-import, not just status codes |

**Articles are created as drafts by default.** This is an advantage — it gives you a review gate before anything goes live. Publish in batches after editorial review.

> [!TIP]
> Document360 has launched **API v3** with OAuth 2.0, scoped API keys, and expanded endpoints including Drive management. The v3 authentication header changes from `api_token` to a Bearer token structure. Existing v2 integrations continue to work, but v3 offers better permission controls and Drive API access for migration scripts. If starting a new integration, use v3. If extending an existing v2 script, test authentication headers before mixing versions.

## API Rate Limits on Both Sides

| Platform | Endpoint | Rate Limit |
|---|---|---|
| Slack | `files.list`, `canvases.getContent` | Tier 3: ~50 requests/minute |
| Document360 | All endpoints (Professional / Business) | 60 writes/min, 120 reads/min per `api_token` |
| Document360 | All endpoints (Enterprise / Enterprise Plus) | 100 writes/min, 200 reads/min per `api_token` |

Document360 rate limits are enforced per `api_token`, and tokens are **project-scoped**. Read requests (GET/HEAD) and write requests (POST/PUT/PATCH/DELETE) have **independent limits**, so a write-heavy migration script does not compete with read calls for quota. ([apidocs.document360.com](https://apidocs.document360.com/apidocs/understanding-rate-limiting))

At 60 writes per minute on a Professional plan, creating 200 articles (one API call each, ignoring image uploads and category creation) takes a minimum of ~3.3 minutes of pure API time. Factor in image uploads (one write per image), publish calls (one write per article), category creation, and retry cycles on 429s, and a 200-article migration with an average of 5 images per canvas realistically consumes 45–90 minutes of API time at the Professional tier. At the Enterprise tier (100 writes/min), that compresses to roughly 25–50 minutes.

Implement exponential backoff unconditionally on every write call. Document360 returns HTTP 429 when the limit is exceeded but does **not** include a `Retry-After` header — your script must determine its own retry interval. A starting backoff of 2 seconds doubling to a maximum of 32 seconds handles most burst scenarios without stalling the pipeline.

## Validating the Migration Post-Import

Every migration guide that stops at "push articles" is incomplete. Silent failures are the norm, not the exception.

**What to check after import:**

1. **Broken image detection.** Fetch each article's rendered HTML and scan for `<img>` tags still pointing to `files.slack.com` domains. These are images that were not re-uploaded. A simple regex check against `files.slack.com` in article content catches all failures.
2. **Markdown render errors.** Search article bodies for raw Slack syntax patterns: `<@U`, `<#C`, `<!date^`. Any match means the rewrite pass missed an instance. Document360 renders these as visible text, not errors.
3. **Heading structure validation.** Check that no article body contains an `<h1>` tag — Document360 uses H1 for the article title, and a second H1 in the body creates duplicate heading hierarchy issues. Canvases that start with an H1 heading will produce this by default.
4. **Empty articles.** Canvas content at or near the 1 MiB limit may have been truncated. Check article word counts against the source canvas sizes.
5. **Slug collisions that resolved incorrectly.** Confirm that every article has a unique URL. A `409 Conflict` that was not caught correctly may have resulted in a silent overwrite depending on how your error handling was structured.
6. **Draft vs. published state.** Confirm no articles were accidentally published before editorial review. Query `GET /v2/Articles` filtered by status and verify draft counts match expectations.

A post-import audit run that checks all six conditions takes roughly an hour to script and prevents the most common category of migration failures from reaching readers.

## Designing Reader Groups — You Cannot Derive Them from Channels

**A Document360 reader group** is an access control construct used in Private or Mixed projects to grant workspace, language, category, or article-level access to many readers at once. ([docs.document360.com](https://docs.document360.com/docs/create-reader-group))

It is tempting to map Slack channel membership to Document360 reader groups. This does not work for three reasons:

1. **Channel membership is not an access policy.** People join Slack channels for notifications, not because they have a defined need to read every document in that channel.
2. **Your audience changes.** The whole point of moving to Document360 is usually to reach people who are *not* in the Slack workspace — customers, partners, or a wider internal audience.
3. **Document360 groups are category-scoped, not document-scoped.** A reader group grants access to categories and their contents. Slack channels are flat; they do not map onto a hierarchical permission model.

Document360 uses project access mode first — **Public**, **Mixed**, or **Private** — and then reader groups for fine-grained control. If the whole project is Public, reader groups do not apply at all. Design groups based on the **intended audience** of the published content: by customer tier, by product line, by role. Set permissions at the Category level and let articles inherit those rules during upload.

## The Practical Migration Sequence

1. **Credential setup** — Collect all Slack bot token scopes (`files:read`, `canvases:read`, `users:read`, `channels:read`) and Document360 API key plus `project_version_id` before starting. Missing any one scope requires reinstalling the Slack app.
2. **Inventory** — Run `files.list?types=canvas` across all channels. Tag each canvas with its channel, author, last-updated date, and tab count (post-April 2025). For multi-tab canvases, enumerate each tab's canvas ID separately.
3. **Triage** — Flag canvases that are outdated, duplicated, or purely internal (incident timelines, 1:1 notes, working drafts). Cut aggressively. A canvas worth migrating answers a question a reader without workspace context would actually ask.
4. **Build the mention map** — Call `users.list` once and build a complete Slack User ID → display name dictionary. Use this throughout the rewrite phase rather than calling the API per mention.
5. **Design the category tree** — Use channel groupings and index canvases as starting points. Create the categories in Document360 first. Capture their IDs.
6. **Extract and rewrite** — Pull markdown via `canvases.getContent`. Rewrite each canvas: strip @mentions, replace channel links, convert date tokens, remove unfurls, collapse multi-column layouts, add context that was previously assumed, and expand headings beyond H3 where the structure is too shallow. Note that canvas comments are not included in the API response — retrieve separately if needed.
7. **Handle images and files** — Download from Slack using the bot token as a Bearer header, upload to Document360 Drive via v3 Drive API or manually if the endpoint is unavailable on your plan, and update all asset references in the markdown.
8. **Push articles** — `POST /v2/Articles` with `content_type: 0` (Markdown). Articles land as drafts. Generate unique slugs using the file-ID suffix method.
9. **Validate post-import** — Check for residual Slack image URLs, raw Slack syntax in article bodies, duplicate H1 headings, empty articles near the 1 MiB boundary, and unexpected publish states.
10. **Review and publish** — Use Document360's review workflow for a final editorial check. Publish in batches.
11. **Configure access** — Set up reader groups if any content is private or mixed. Assign groups to categories based on intended audience, not source channel membership.

## What This Migration Actually Costs in Time

The API work — extracting, transforming, and pushing content — is the smaller part. A competent engineer can build the extraction and loading scripts in a day or two. The rewrite pass is where the real time goes.

Editorial time per canvas breaks down roughly as:
- **Mention and syntax cleanup** (automated): 0 minutes per canvas if scripted correctly
- **Context gap assessment** — reading the canvas and identifying what a non-workspace reader would not understand: 5–10 minutes per canvas
- **Active rewriting** — expanding shorthand, removing dead references, restructuring headings: 10–20 minutes per canvas for a typical 500–800 word internal doc
- **Image verification** — confirming re-uploaded images render correctly: 2–5 minutes per canvas

Total: roughly **20–35 minutes per canvas** for editorial work, assuming automation handles the syntax transformation. A workspace with 100 canvases means 35–60 hours of editorial work. That estimate scales linearly — the API pipeline does not change that number.

If the editorial burden is more than your team can absorb alongside regular work, that is the point where bringing in help makes sense.

> ClonePartner has moved content out of Slack workspaces and into structured knowledge bases for teams that needed the migration done in days, not months. If you want the API pipeline handled so your team can focus on the editorial rewrite, book a 30-minute call.
>
> [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

### Can I export all Slack Canvases at once into Document360?

No. Document360 has no native Slack Canvas importer, and Slack has no Document360 export. Use the Slack API files.list endpoint filtered by types=canvas to build your inventory, then fetch each canvas body with canvases.getContent. Content still needs rewriting, taxonomy design, and media re-upload before it belongs in Document360.

### What happens to @mentions when migrating Slack Canvas to Document360?

@mentions export as Slack user IDs (e.g., <@U071CCRCVFH>) in the markdown. Outside Slack, they are meaningless strings. Every mention must be replaced with a real name, a role description, or removed entirely during the editorial rewrite.

### Does Document360 accept Slack Canvas Markdown directly?

Document360 accepts standard Markdown, but Slack's proprietary tags for user mentions, channel links, and date formatting must be converted first. The v2 API takes Markdown in the content field with content_type 0; the newer v3 API accepts content plus a content_type parameter.

### Are Slack Canvas images accessible outside of Slack?

No. Slack-hosted images require authentication via a bearer token. Anyone without a valid Slack session sees a sign-in page. You must download each image with a Slack token and re-upload it to Document360 Drive, then update the image URLs in the article markdown.

### How do I organize Slack Canvas content into Document360 categories?

Slack Canvas has no folder concept. Design the category tree using channel names as starting points, index canvases (master canvases that link to others) as grouping signals, and editorial judgment for docs that do not fit a channel-based structure. Create all categories in Document360 before pushing articles.
