---
title: "Quip to Slack Canvas Migration: Comments, Annotations & @date"
slug: quip-to-slack-canvas-migration-comments-annotations-date
date: 2026-09-30
author: Abdul Wahab
categories: [Quip, Slack Canvas, Migration Guide]
excerpt: "Quip inline annotations, thread messages, and @date mentions all degrade or disappear in a Slack Canvas migration. Here is what happens to each and what your real options are."
tldr: Quip inline annotations are structurally unrecoverable in Slack Canvas — section IDs don't survive export and no Slack API can anchor a comment to a canvas position. Plan for appendix-style preservation or PDF archival.
canonical: https://clonepartner.com/blog/quip-to-slack-canvas-migration-comments-annotations-date
---

# Quip to Slack Canvas Migration: Comments, Annotations & @date


# Quip to Slack Canvas Migration: Comments, Annotations & @date

When you migrate Quip documents to Slack canvases, the document body transfers with reasonable fidelity. The comments do not. Quip has three distinct comment types — inline annotations, thread messages, and page-level comments — and each one degrades or disappears in the move to Slack Canvas. The `@date` mention, a Quip-native inline element, has no Canvas equivalent at all.

This guide covers what actually happens to each element, why inline annotations are structurally unrecoverable, what your realistic preservation options are, and what to do when extraction goes wrong mid-run.

**Scope note:** This guide covers Quip document comments. Quip spreadsheet cell comments have a different internal structure (anchored to cell coordinates rather than section IDs) and are treated as out of scope here — they warrant separate handling and are noted where behavior diverges.

Salesforce reports that [roughly **65% of Quip documents** are compatible with Slack Canvas](https://clonepartner.com/blog/blog/what-the-quip-to-slack-canvas-converter-doesnt-migrate), and even compatible documents may simplify formatting, flatten unsupported mentions to plain text, and alter comment structure. ([help.salesforce.com](https://help.salesforce.com/s/articleView?id=005387799&language=en_US&type=1))

## The Structural Mismatch Between Quip and Slack Canvas

Quip and Slack Canvas operate on fundamentally different architectural models, and this mismatch is why comments and dates break during migration.

Quip uses a **document-as-a-thread** model. Every document, spreadsheet, or chat room is a `thread` object in the Quip API. Within a document, every paragraph, list item, and table cell is a distinct node with a unique `section_id`. When a user highlights text and leaves a comment, Quip creates an `annotation` object anchored to that specific `section_id`. This is a strong location model — comments have precise positional context. ([quip.com](https://quip.com/dev/automation/documentation/all))

Slack uses a **canvas-as-a-file** model. A Slack Canvas is a block-kit document stored as a file object. While you can leave comments on a Canvas through the UI, those comments are functionally threaded messages that sit beside the canvas, not inside it. The entire public Slack Canvas API surface consists of six methods: `canvases.create`, `canvases.edit`, `canvases.delete`, `canvases.access.set`, `canvases.access.delete`, and `canvases.sections.lookup`. None of these create or manage comments. ([api.slack.com](https://api.slack.com/methods/canvases.edit))

> [!WARNING]
> **The core limitation:** You cannot programmatically insert a comment into a Slack Canvas at a specific position. The Slack Canvas API has no comment-creation endpoint. This is not a limitation a custom script can overcome — it is a missing API capability on the Slack side.

## The Three Quip Comment Types You Need to Distinguish

Quip's commenting model is more complex than most collaborative editors. A single Quip document thread can contain three structurally different kinds of comments, and they are stored and retrieved differently via the API. All three types come through the same `Get Recent Messages` endpoint, which returns 25 messages by default (max 100 per call) and requires pagination for full history. The presence or absence of an `annotation` field in the API response is the reliable programmatic discriminator between types.

### Inline annotations

**An inline annotation is a comment anchored to one or more specific section IDs within a Quip document.** When a user highlights a paragraph or sentence and adds a comment, Quip stores that comment as a message with an `annotation` object containing an `id` and an array of `highlighted_section_ids`.

The API response includes this structure:

```json
{
  "annotation": {
    "id": "string",
    "highlighted_section_ids": ["string"]
  }
}
```

This is the comment type that carries positional context — the reader can see exactly which text the comment refers to. It is also the most common and most valuable type, as it provides direct context for edits, approvals, and questions. **Quip spreadsheet comments use cell coordinates rather than section IDs, so this structure does not apply to spreadsheet cells.**

### Thread messages

**Thread messages are the chat-style conversation that runs alongside every Quip document.** Every Quip document is a "thread," and that thread has a built-in message stream. These messages appear in the conversation pane, not anchored to any specific location in the document body. They include user messages, system events (like "Alice edited the document"), and status updates.

Thread messages are structurally the easiest to migrate. Because they apply to the whole document, they map cleanly to Slack's thread model — a Slack message thread attached to the Canvas.

The catch: **authorship and timestamps**. When writing via the Slack API, messages appear as posted by the migration bot at the time of migration, unless you use Slack's specialized import APIs or format the message blocks to explicitly state the original author and date (e.g., `[2024-03-12] Alice: Looks good to me`).

### Page-level comments

**Page-level comments are messages posted about the document as a whole rather than a specific section.** They appear in the same message stream as thread messages but are user-authored feedback about the entire page. In the API response, they look like standard messages without an `annotation` field.

Like thread messages, page-level comments can be migrated to Slack without losing positional context, because there was no positional context to begin with. The primary challenge remains preserving the original timestamp and author identity.

> [!NOTE]
> **Naming trap:** Quip's help content talks about **inline comments** and the **conversation pane**. Teams often say "page-level comment" for a comment targeting a whole block, image, or document area rather than a highlighted phrase. Treat that as a weakly anchored comment, not as the same thing as a conversation-pane message. The programmatic distinction: inline annotations have an `annotation` field; page-level and thread messages do not. ([help.salesforce.com](https://help.salesforce.com/s/articleView?id=000389933&language=en_US&type=1))

## Why Inline Annotations Are Structurally Unrecoverable

Inline annotations are the hardest case in a Quip-to-Canvas migration — not because of a bug or rate limit, but because of an architectural mismatch that has no workaround.

The problem has two halves:

**Half one: Quip section IDs do not survive export.** Quip's Automation API outputs documents as HTML where each paragraph, list item, and table cell carries an `id` attribute corresponding to its internal section ID. But when you export that document — via the GUI (HTML, DOCX, PDF) or the Bulk Export API — those Quip-internal `id` attributes are stripped or become meaningless outside Quip. The annotation's `highlighted_section_ids` reference identifiers that no longer exist in the exported artifact.

**Half two: Slack's Canvas API has no mechanism to anchor a comment to a position within a canvas.** The `canvases.sections.lookup` method can help you find Slack section IDs for headings and text matching, but there is no API call to say "attach this comment to this canvas section." The operation does not exist. Canvas comments can only be created manually through the Slack UI by highlighting text and clicking "Add Comment." ([api.slack.com](https://api.slack.com/methods/canvases.edit))

The practical outcome: you can extract the annotation text, the author, the timestamp, and the raw `highlighted_section_ids` from Quip. But you cannot place that comment back onto the corresponding paragraph in a Slack Canvas. Once exported, the positional link is permanently severed.

### Building a human-readable anchor map

The standard mitigation is to build an anchor map before exporting — a lookup table that translates each `section_id` to a human-readable location while Quip is still live. Here is a concrete example of what that mapping looks like:

| Quip section_id | Heading path | Nearby text excerpt | Comment author | Comment text |
|---|---|---|---|---|
| `ABC123` | `Q4 Plan > Revenue Projections` | "...total pipeline adjusted for..." | alice@co.com | "These numbers need updating post-board meeting." |
| `DEF456` | `Q4 Plan > Risk Factors > Item 3` | "...regulatory approval timeline..." | bob@co.com | "Legal confirmed this is still open." |

To build this map programmatically: call `GET /threads/{thread_id}?columns=html` to retrieve the document HTML, parse each element with an `id` attribute, walk the DOM to reconstruct the heading hierarchy above each element, and extract a 100–150 character excerpt of surrounding text. Store the result as a structured JSON or CSV alongside your comment export.

A good pre-migration archive stores at minimum: the original Quip thread ID, the message/comment ID, the annotation section ID, any highlighted section IDs, the author identity, the timestamp, the heading path, and the nearby text excerpt. Without the heading path and excerpt, your archive tells you **what** was said but not **where** it was said.

## What Happens to @date Mentions

**Quip `@date` mentions degrade to static plain text during migration.** Slack Canvas does not have a native `@date` mention type that can be created via API. The interactive behavior — clickable dates, reminders, notifications to mentioned users — is permanently lost. Any active reminders tied to those dates stop working immediately.

In Quip, typing `@` followed by a date creates an interactive element that can trigger notifications, change color as the date approaches, and integrate with task lists. In the HTML export, this element renders as a `<time>` tag or a proprietary span containing a timestamp. When converted to Slack's block-kit format, the dynamic properties are stripped, leaving a static string like `2024-10-15`.

Salesforce's conversion FAQ confirms that mentions not supported in Slack may become plain text. ([help.salesforce.com](https://help.salesforce.com/s/articleView?id=000389481&language=en_US&type=1))

The nuance: Slack canvases support dates entered natively in the Slack UI, and users can set reminders from those dates. But Slack's `canvases.edit` API lists supported `@` mentions for **users and channels** only — not dates. A human can recreate a date in the Slack UI, but an automated migration pipeline cannot produce a Slack-native interactive date object via API. Hoping the converter will preserve the semantics is how teams end up with deadlines that still look readable but no longer notify anyone.

The safe pattern: preserve the visible date text, normalize ambiguous formats to ISO 8601 (YYYY-MM-DD) during extraction so dates are unambiguous, and document reminder behavior separately. If a date drives work, approvals, or escalation, recreate it deliberately in Slack after the document body lands.

> [!NOTE]
> **Salesforce Data Mentions and user identity are separate issues.** Quip supports `@mentioning` Salesforce record fields inline (e.g., an Opportunity's close date). These are live-linked CRM data pulls and do not survive migration — they render as blank or static text in exports.
>
> Quip also uses Salesforce user identities (User IDs, email addresses) which do not map automatically to Slack user IDs. A migration pipeline that preserves authorship must maintain an explicit Quip-user-ID → Slack-user-ID lookup table, built from your identity provider, HR system, or manual cross-reference. Without this, comment attribution will appear as email addresses or be attributed to the migration bot.

## Practical Options for Preserving Comment History

There is no option that restores full fidelity. Every approach involves a trade-off between accessibility, context preservation, and engineering effort.

### Option 1: Export the comment stream as a canvas appendix

Extract all comments using the Quip `Get Recent Messages` API, paginating to get full history. For each comment, capture the author, timestamp, text, and — for annotations — the heading path and text excerpt from your anchor map. Append a structured comment log to the bottom of the Slack Canvas using `canvases.edit` with an `insert_at_end` operation.

The appendix might look like:

```markdown
## Comment Archive

**@alice** (2025-12-03, on: "Q4 Plan > Revenue Projections — ...total pipeline adjusted for...")
> These numbers need to be updated after the board meeting.

**@bob** (2025-12-04, page-level)
> Overall looks good, but check the formatting on the tables.
```

**Pros:** Comments are preserved in the same artifact as the document. Searchable in Slack. No separate system needed.

**Cons:** Inline positional context is text-based, not interactive. Long comment histories bloat the canvas. Slack Canvas content is limited to **1 MiB** per `document_content` object.

**Handling the 1 MiB limit:** When a comment appendix approaches the size cap, use one of three strategies: (a) split the canvas into a primary document canvas and a linked "Comment Archive" canvas using `canvases.create` plus a reference link; (b) truncate to the most recent N comments by timestamp and note the cutoff date explicitly; or (c) move the full archive to a Slack-linked Google Doc or Confluence page and insert a single reference block in the canvas. Strategy (a) preserves the most data; strategy (b) is appropriate when only recent context matters; strategy (c) is best for compliance archives that need to remain searchable but are rarely accessed.

### Option 2: Post comments as a channel thread

Instead of appending to the canvas, post the comment archive as messages in the Slack channel thread associated with the canvas. Use `chat.postMessage` with the `thread_ts` of the canvas's parent message.

To keep this manageable, batch comments into grouped block-kit messages rather than posting one message per comment. Slack's rate limit for `chat.postMessage` is **1 request per second** per workspace at the base tier — at that rate, a document with 500 comments posted individually takes over 8 minutes and occupies the rate limit for the entire workspace. Batching 10–20 comments per message reduces this to 25–50 API calls.

**Pros:** Keeps the canvas body clean. Channel threads are a natural Slack pattern. Comments are searchable.

**Cons:** Comments are separated from the document. Harder to find months later. Retention follows Slack message policies, so this is not a substitute for a preserved source archive. ([slack.com](https://slack.com/help/articles/15708101445011-How-data-management-features-apply-to-canvases-and-lists))

### Option 3: Accept the loss and archive the Quip export

Export Quip documents as PDFs using the Bulk Export API and store those PDFs as your canonical record. Migrate only the document body to Slack Canvas for daily use, and point compliance or audit teams to the archived PDFs for comment history. According to Salesforce's Bulk Export documentation, PDF exports include conversation history (thread messages and page-level comments); inline annotations render in the PDF margin with their highlighted text visible. ([help.salesforce.com](https://help.salesforce.com/s/articleView?id=sf.quip_export.htm&type=1))

**Pros:** Zero risk of comment data loss in the archive. PDF is a legally accepted format. Cleanest migration — zero clutter in Slack.

**Cons:** Two systems to maintain. Users must check a secondary system for historical context.

> [!TIP]
> If you choose the archive route, capture the `GET /threads/{id}` JSON payload alongside the PDF export. The PDF serves human readers; the JSON serves eDiscovery tools and allows future programmatic processing if your compliance requirements change. Relying on just one format is a compliance risk.

### Decision reference: comment type × migration option

| Comment Type | Appendix (Option 1) | Channel Thread (Option 2) | PDF Archive (Option 3) |
|---|---|---|---|
| **Inline annotations** | Heading path + text excerpt included; positional anchoring lost | Same as appendix but in thread form | Preserved with visual margin position in PDF |
| **Thread messages** | Appended chronologically; no anchoring needed | Natural fit — thread messages become thread messages | Included in bulk export PDF |
| **Page-level comments** | Appended with "page-level" label | Posted as top-level thread replies | Included in bulk export PDF |
| **@date mentions** | Degraded to plain text in canvas body | Not applicable (body content, not comment) | Rendered as static text in PDF |
| **Spreadsheet cell comments** | Not covered by this guide | Not covered by this guide | May be included depending on export format |

### Decision tree: which option to choose

```
Does your Quip content have regulatory retention, legal hold, or audit requirements?
├── YES → Option 3 (PDF archive) is mandatory as baseline
│         ├── Do users need searchable comments in Slack daily? → Add Option 1 or 2
│         └── No daily access needed → Option 3 alone is sufficient
└── NO → Is comment history referenced regularly by active users?
          ├── YES → Is engineering capacity available for extraction scripting?
          │         ├── YES → Option 1 (appendix) for rich documents; Option 2 for lighter ones
          │         └── NO → Accept loss; migrate body only
          └── NO → Accept loss; migrate body only
```

## Failure Modes and Partial Extraction

Rate limit and interruption errors are the most common cause of incomplete comment extraction. Understanding what gets silently dropped versus loudly errored prevents false confidence in your archive.

### What the Quip API rate limit means in practice

The Quip API enforces a [limit of **50 requests per minute per access token**](https://clonepartner.com/blog/blog/quip-to-slack-canvas-migration-at-scale-api-limits-scripting-guide). Comment extraction requires at minimum two API calls per document: one `GET /threads/{id}` call for the document HTML (needed for the anchor map), and one or more `GET /threads/{id}/messages` calls for the comment stream (paginated at up to 100 messages per call).

For a 10,000-document workspace:
- **Anchor map extraction:** 10,000 calls ÷ 50/min = **200 minutes minimum** (3.3 hours), assuming no retries and no other API usage on the same token
- **Comment extraction (1 page per doc):** another 200 minutes minimum
- **Comment extraction with pagination (avg. 3 pages per doc):** ~600 minutes (10 hours)

In practice, add 30–50% for retries, error handling, and throttling backoff. A complete comment extraction for a 10,000-document workspace should be budgeted at **15–20 hours of continuous API runtime**. Use a dedicated access token for migration work to avoid starving other Quip integrations during the extraction window.

### Failure modes to monitor

**Silent data loss:** Pagination errors are the most dangerous failure mode because they appear to succeed while truncating data. If your pagination loop encounters a network timeout or a 429 rate-limit response mid-page and fails to retry, the next iteration may continue from the wrong cursor or restart from the beginning, producing a duplicate-but-incomplete record. Mitigation: log the cursor value and message count after every paginated call; compare the total retrieved against the `thread.message_count` field available in the thread metadata before closing the extraction for that document.

**Loud errors (safe failures):** HTTP 403 responses indicate the access token lacks permission to read that thread's messages. HTTP 404 responses indicate the document was deleted or moved. Both are loud — they will surface in your error log — and both mean the document should be flagged for manual review rather than silently skipped.

**Partial anchor maps:** If the document HTML call succeeds but the message call fails, you have an anchor map with no comments attached. This is preferable to the reverse (comments with no anchor map), but both states should be flagged. A complete record requires both the HTML parse result and the message extract for the same thread ID.

**Recommended extraction pattern:**

```
For each document:
  1. GET /threads/{id}?columns=html → store HTML, parse section IDs → anchor map
  2. GET /threads/{id} → read thread.message_count → store as expected_count
  3. Paginate GET /threads/{id}/messages until cursor exhausted
  4. Compare retrieved_count to expected_count
  5. IF retrieved_count < expected_count → flag for retry/manual review
  6. Mark document as COMPLETE only when both steps succeed and counts match
```

Track document status (PENDING, IN_PROGRESS, COMPLETE, FAILED) in a persistent store, not in memory. A migration run that crashes at 6,000 documents should resume at document 6,001, not restart from zero.

## When Compliance or Audit Requirements Change the Answer

**Regulated industries (finance, healthcare, legal):** If your Quip comment history includes discussions about compliance decisions, customer data handling, or audit-relevant approvals, Option 3 is mandatory as a baseline. Layer Option 1 or 2 on top for day-to-day usability, but the PDF and JSON export are your legal backstop.

**SOC 2 or ISO 27001 obligations:** If your documentation process is part of an auditable control, you need to demonstrate that decision history was preserved during migration. An appendix (Option 1) creates a visible, searchable record within the destination system. Document the mapping methodology and keep a log of which Quip thread IDs map to which Canvas IDs — this mapping log is itself an audit artifact.

**No regulatory constraints:** If comments are informal collaboration artifacts with no retention requirements, accepting the loss is the pragmatic call. Spending engineering cycles reconstructing comment anchors for informal discussion threads is rarely worth it.

If auditors rely on inline comments to prove that peer reviews, approval workflows, or security sign-offs occurred — and those comments were anchored to specific paragraphs — losing the anchor degrades the audit trail. Document this fidelity loss explicitly for your compliance team before migration, not after.

On the Slack side, Enterprise Grid plans offer Discovery API coverage for canvas comments and version history, plus legal holds that can override retention. But Slack admins can also disable canvas version history and set [retention policies that permanently delete canvases](https://clonepartner.com/blog/blog/slack-canvas-retention-ediscovery-compliance-guide) and comments. A compliance-safe plan starts by freezing the Quip record first, then converting — not the other way around. ([slack.com](https://slack.com/help/articles/15708101445011-How-data-management-features-apply-to-canvases-and-lists))

> [!WARNING]
> **Audit your Quip documents for legal holds before migrating.** After the Quip subscription expires, data enters a [wind-down period ending in permanent deletion](https://clonepartner.com/blog/blog/quip-to-slack-canvases-migration-the-official-salesforce-path). If any document is under legal hold, you must extract and archive it — including comments — before access is blocked. The API stops working once the blocked-login phase begins. A complete extraction for a large workspace can take 15–20 hours; do not start this process in the final week of your subscription.

## Third-Party Migration Tooling

No third-party migration tool currently advertises full-fidelity Quip inline annotation transfer to Slack Canvas, because the target platform's API does not support it. However, several tools handle portions of the migration and may reduce scripting effort:

- **Egnyte and Cloudficient** support Quip document body export and can target multiple destinations, but their Canvas-specific handling is limited to document content — comments are typically excluded or handled via separate archival workflows. Verify comment handling explicitly with the vendor before purchasing.
- **Spinbackup** focuses on SaaS backup rather than migration; it can create a Quip snapshot archive (useful as an Option 3 baseline) but does not write to Slack Canvas.
- **[Salesforce's native migration tool](https://clonepartner.com/blog/blog/quip-to-slack-canvases-migration-the-official-salesforce-path)** (accessed via the Slack admin panel for orgs with active Salesforce + Slack integration) handles document body conversion for the 65% of compatible documents but does not migrate comment history.

For custom comment extraction and anchor mapping, a purpose-built script using the Quip Automation API is currently the only approach that captures the full annotation structure. The extraction pattern described in the failure modes section above is the starting point for that script.

## What to Do Before You Migrate

1. **Inventory your comment volume.** Use the Quip `Get Recent Messages` API to sample representative documents. Identify which have annotations (check for the `annotation` field), which have long thread histories, and which use `@date` mentions. Check `thread.message_count` in the thread metadata to estimate extraction time before committing.

2. **Check for legal holds and retention policies.** Any document under hold needs a PDF export regardless of your migration strategy.

3. **Build your identity map.** Compile a Quip-user-ID to Slack-user-ID lookup table before extraction begins. Without it, comment authorship in the archive defaults to email addresses or migration bot attribution.

4. **Extract source data while Quip is live.** Pull API HTML for section IDs, comment/message data, and PDFs with conversation history. Budget 15–20 hours of API runtime for a 10,000-document workspace. Do not leave this for the last week of your active subscription.

5. **Build the anchor map during extraction, not after.** Parse Quip section IDs to heading paths and text excerpts in the same pass as the HTML download. Doing it as a second pass doubles API calls and doubles the time.

6. **Choose one preservation pattern per document class.** Decide up front whether comments become an appendix, a Slack thread, or remain only in the archived Quip record. High-traffic documents with dense annotation history may warrant an appendix; low-comment documents can migrate body-only. Do not improvise per comment halfway through the run.

7. **Handle the 1 MiB canvas limit proactively.** Flag documents where estimated comment volume may approach the limit before the migration run. Pre-decide whether to split, truncate, or externalize for each flagged document.

8. **QA with real stakeholders.** Have document owners and compliance reviewers sign off on a sampled batch before broad rollout. Verify the chosen treatment is acceptable for each risk tier.

## What This Means for Your Migration

The migration from Quip to Slack Canvas is a structural downgrade in document collaboration depth. Quip was built as a dedicated document platform with node-level architecture and a strong comment-anchoring model. Slack Canvas is a lightweight text surface attached to a chat application. Only about 65% of Quip documents are Canvas-compatible to begin with, and even those lose comment metadata, interactive mentions, and positional anchoring.

No script, middleware, or API workaround will force Slack Canvas to support inline annotations or dynamic `@date` mentions — the target API does not expose these capabilities. The most defensible migrations acknowledge this limitation before extraction begins: they build a complete, compliance-grade archive of the Quip instance (JSON + PDF), move only the living text to Slack Canvas, and treat the migration as a clean break rather than a perfect mirror.

If you only remember one thing: **Quip comments are not just text — they are location, attribution, and workflow state.** Slack Canvas can hold the document body and follow-on discussion, but it is not a one-to-one container for Quip's inline annotation model. Treat inline annotations as lossy, normalize `@date` to plain ISO 8601 text, resolve user identity before export, and choose your preservation strategy based on compliance burden — not on optimism about what the conversion tool will handle automatically.

> Need to preserve Quip comment history, inline context, or audit evidence on the way to Slack? We build custom comment-extraction pipelines, anchor maps, and compliance archives for Quip workspaces. Book a technical scoping 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 migrate Quip inline comments directly into Slack Canvas?

No. Quip inline annotations depend on internal section IDs and highlighted ranges, while Slack's public Canvas API has no comment-creation or comment-anchoring endpoint. The positional link between an inline annotation and the text it references is structurally unrecoverable. You must extract comments separately via the Quip Get Recent Messages API and preserve them as an appendix, a channel thread, or a PDF archive.

### What happens to Quip @date mentions during migration to Slack Canvas?

Quip @date mentions degrade to static plain text. Slack Canvas has no equivalent inline date-mention type — it supports @mentions for users and channels but not dates. The interactive behavior (clickable dates, reminders, notifications) is permanently lost. Active reminders stop working immediately upon migration. If a date drives deadlines or escalation, you must recreate it manually in Slack after the document body lands.

### How should I preserve Quip comments for compliance or audit purposes?

For regulated content, export Quip documents as PDFs using the Bulk Export API, which includes comments in the PDF output. This provides a legally defensible archival record with visual positioning of inline annotations. Capture the JSON payload from GET /threads/{id} alongside the PDF — the PDF serves human readers, the JSON serves eDiscovery tools. Extract comments before the Quip read-only phase begins, as the API stops working once logins are blocked.

### Does the Slack Canvas API support adding comments programmatically?

No. The Slack Canvas API consists of six methods: canvases.create, canvases.edit, canvases.delete, canvases.access.set, canvases.access.delete, and canvases.sections.lookup. None of these create or manage canvas comments. Comments can only be added manually through the Slack UI by highlighting text and clicking Add Comment.

### Can I export Quip comments before moving to Slack?

Yes. Use the Quip Get Recent Messages API to extract all comments (inline annotations, thread messages, and page-level comments), paginating to retrieve full history. GUI export alone is not enough — Quip's GUI export does not include comments. The API rate limit is 50 requests per minute per token, so for large workspaces, comment extraction can take hours. Plan accordingly.
