> ## Documentation Index
> Fetch the complete documentation index at: https://modem.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Canny

> Capture feature requests, bug reports, and comments from Canny boards

export const Prompt = ({text, variant = 'accent'}) => {
  const [copied, setCopied] = useState(false);
  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {}
  };
  const clipboardIcon = <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <title>Copy</title>
            <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
            <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
        </svg>;
  const checkIcon = <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <title>Copied</title>
            <polyline points="20 6 9 17 4 12" />
        </svg>;
  const promptIcon = <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style={{
    flexShrink: 0,
    opacity: 0.4
  }}>
            <title>Prompt</title>
            <path d="M20 2H2v20h2V4h16v12H6v2H4v2h2v-2h16V2zM6 7h12v2H6zm8 4H6v2h8z" />
        </svg>;
  return <div className={`prompt prompt-${variant}`} style={{
    marginTop: '12px',
    marginBottom: '12px'
  }}>
            {promptIcon}
            <span className="prompt-text">{text}</span>
            <button className="prompt-copy" onClick={handleCopy} title="Copy to clipboard" type="button">
                {copied ? checkIcon : clipboardIcon}
            </button>
        </div>;
};

The Canny integration captures posts and comments from your Canny feedback boards in real time. Every feature request, bug report, and the comment thread beneath it flows into Modem, where it is grouped into [topics](/docs/guides/topics), classified by type, and linked to the [people and companies](/docs/guides/people) behind it.

<Info>
  Canny is **capture-only** and read-only. Modem ingests posts, comments, and vote counts; it never writes anything back to Canny, and the
  Modem Agent has no tools for taking action inside Canny. You query captured Canny feedback from the [Modem Agent on the
  web](/docs/features/agent), where the agent can still act on what it finds in your other connected tools.
</Info>

## How it works

Modem connects to Canny with your workspace **API key**. When you paste the key, Modem validates it by listing your boards, identifies the workspace from a board URL, and stores the key encrypted.

Canny has no API for registering webhooks, so the second half of setup is manual: Modem shows you a webhook URL for your connection, and you paste it into Canny. From then on Canny pushes post and comment activity to Modem as it happens. Each delivery is signed with your API key and time-stamped, and Modem rejects deliveries that fail verification or arrive more than five minutes late.

API keys in Canny don't expire, so there's no re-authorization cycle. Capture is webhook-based and real-time: a new post typically shows up in Modem within a few minutes.

## Prerequisites

* **Owner or admin** role in your Modem organization, to connect and manage the integration
* Admin access to your Canny workspace, to copy the API key and add a webhook
* A Canny plan that includes API and webhook access
* At least one board in the workspace (Modem uses a board URL to identify the workspace)

## Setup

<Steps>
  <Step title="Copy your Canny API key">
    In your Canny admin, go to **Settings** → **API** (`https://<your-workspace>.canny.io/admin/settings/api`) and copy the workspace
    API key. One key covers every board in the workspace.
  </Step>

  <Step title="Paste the key into Modem">
    Go to **Settings** → **Integrations** → **Canny** in your Modem dashboard, paste the key, and click **Connect Canny**. Modem
    verifies it against your boards and encrypts it before storing.
  </Step>

  <Step title="Add Modem's webhook in Canny">
    Once connected, the settings page shows a **Finish setup in Canny** card with your webhook URL. Copy it, open **Settings** → **API
    & Webhooks** in Canny, add a webhook with that URL, and save. See [Adding the Webhook](#adding-the-webhook) below.
  </Step>

  <Step title="Optionally run a backfill">
    Import your workspace's existing posts so past feedback shows up too. See [Historical Backfill](#historical-backfill) below.
  </Step>
</Steps>

## Adding the Webhook

Connecting stores your API key, but nothing arrives until the webhook is in place. Until then the integration shows as connected, and hovering over the status explains that no webhook has arrived yet.

The webhook URL looks like this, where the trailing number is the id of your connection:

```
https://canny.services.modem.dev/webhook/<connection-id>
```

* The URL belongs to this connection. Reconnecting the same Canny workspace, for example after rotating the API key, keeps it working.
* Connecting a **different** Canny workspace issues a new URL that has to be pasted into that workspace's settings.
* Anyone who can view the settings page can copy the URL, so a team member can hand it to whoever administers Canny.

<Note>
  If your boards are served from a custom domain rather than `<workspace>.canny.io`, Modem can't link straight to your Canny admin. Open
  your Canny admin directly and find **Settings** → **API & Webhooks** there.
</Note>

## What Gets Captured

All boards in the workspace are captured. There is no board picker: each board becomes its own channel in Modem, and a board you create later starts flowing as soon as Canny sends its first event.

### Posts and comments

Each Canny post is captured as one conversation. The post itself, with its title and body, is the opening message, and each comment is a reply in the same conversation. Screenshots and other images attached to a post or comment are captured too, and any text in them is extracted for analysis.

Modem reacts to these Canny events:

| Canny event               | What Modem does                                  |
| ------------------------- | ------------------------------------------------ |
| Post created              | Creates the conversation and its opening message |
| Post edited               | Updates the post's title, body, and images       |
| Post status changed       | Records the new status on the conversation       |
| Comment created or edited | Adds or updates the reply                        |
| Vote added or removed     | Updates the post's vote count                    |

Deletions, tag changes, and Jira links are ignored. A post or comment deleted in Canny stays in Modem.

### Post status

Canny's default statuses are mapped onto Modem's conversation states:

| Canny status | Modem state |
| ------------ | ----------- |
| Open         | Open        |
| Under review | Open        |
| Planned      | Waiting     |
| In progress  | In progress |
| Complete     | Done        |
| Closed       | Canceled    |

Custom statuses you've added to a board are kept as-is on the post but don't map to a Modem state.

### Votes

A post's vote count is the demand signal a feedback board exists to carry, so Modem records it as an **upvote reaction** on the post's opening message. The count always reflects the post's current score in Canny, and it updates whenever a vote is added or removed.

<Note>
  A post whose score drops to zero keeps its last recorded count until the next vote arrives. This is a limitation of how reactions are
  stored and will correct itself on the next vote.
</Note>

### Authors

Post and comment authors are captured with their Canny name and, when Canny has one, their email address, so they resolve to Modem [people](/docs/guides/people). Canny's admin flag is preserved, which lets Modem tell your own team's replies apart from end-user feedback. Posts from deleted or anonymous Canny users are captured without an author.

## Historical Backfill

Connecting only captures activity from that point forward. To pull in what your workspace already has, run the optional backfill from **Settings** → **Integrations** → **Canny**. It imports your full post history — no date cutoff — up to **10,000 posts** across all boards, along with up to 500 comments per post.

The backfill runs in the background and doesn't block real-time capture. Canny's API is rate-limited, so a busy workspace can take a while. The card shows progress, and you can run it again if it fails; re-running won't duplicate posts.

## Analyzing Canny Feedback

Once posts are flowing, ask the [Modem Agent](/docs/features/agent) about them from the web dashboard like any other source.

<Prompt text="What are the most-voted feature requests in Canny this month?" />

<Prompt text="Summarize the bug reports on our Canny boards that are still open" />

<Prompt text="Create a ticket for the top Canny request and link the people who asked for it" />

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connecting says Canny rejected the API key">
    Copy the key again from your Canny admin under **Settings** → **API** and make sure you're pasting the whole value. If the key was
    regenerated in Canny, the old one no longer works.
  </Accordion>

  <Accordion title="Connecting says the workspace has no boards">
    Modem identifies your workspace from a board's URL, and a workspace with no boards has nothing to capture. Create a board in Canny,
    then connect again.
  </Accordion>

  <Accordion title="Connected, but no posts are appearing">
    Check the **Finish setup in Canny** card on the Canny settings page. Nothing arrives until the webhook URL shown there is added in
    Canny under **Settings** → **API & Webhooks**. Once it is, allow a few minutes for delivery and processing. Modem only captures
    activity that happens after the webhook is in place; run the [backfill](#historical-backfill) for the posts you already have.
  </Accordion>

  <Accordion title="I regenerated my API key in Canny">
    Canny signs webhook deliveries with the API key, so after a regeneration Modem can't verify them and stops accepting posts.
    Reconnect on the Canny settings page with the new key. Because it's the same workspace, your webhook URL stays the same and nothing
    needs to change in Canny.
  </Accordion>

  <Accordion title="The backfill seems incomplete">
    The backfill imports your full post history, but it stops at 10,000 posts across all boards, so a very large workspace won't be
    imported in its entirety. Each post is capped at 500 comments. If a run failed, the card shows the error and a **Run again** button.
    If it still looks wrong, contact [support@modem.dev](mailto:support@modem.dev).
  </Accordion>

  <Accordion title="Authors aren't linking to people">
    Authors are matched to Modem people by email address. Canny only includes an email for identified users, so anonymous or deleted
    users won't be linked.
  </Accordion>
</AccordionGroup>

## Disconnecting

To disconnect Canny:

1. Go to **Settings** → **Integrations** → **Canny**
2. Click **Disconnect** and confirm
3. In Canny, delete the Modem webhook under **Settings** → **API & Webhooks**

Modem stops accepting deliveries from the workspace immediately. Canny has no API for removing webhooks, so the third step is yours; until you do it, Canny keeps sending deliveries that Modem rejects. Historical data remains in Modem after disconnecting.

## Related

<CardGroup cols={2}>
  <Card title="The Modem Agent" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/bot.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=2496f9106cb54fa9f4e27ad1f8f3a171" href="/docs/features/agent" width="22" height="22" data-path="icons/bot.svg">
    Query and act on your captured Canny feedback from the web.
  </Card>

  <Card title="Topics" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/label-alt-multiple.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=e7fbaf23c28396ac670b89cf38e1e4a6" href="/docs/guides/topics" width="24" height="24" data-path="icons/label-alt-multiple.svg">
    See how posts and comments are grouped into themes and classified.
  </Card>

  <Card title="Companies & People" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/contact.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=727cb0ef6c8547993c6acfdaa30bd837" href="/docs/guides/people" width="24" height="24" data-path="icons/contact.svg">
    Understand how Canny authors are linked into unified profiles.
  </Card>

  <Card title="All Integrations" icon="https://mintcdn.com/modem-844d7a4a/Wr2r4IRr97lNQiQb/icons/link.svg?fit=max&auto=format&n=Wr2r4IRr97lNQiQb&q=85&s=e774d33588635d44c6c935b78ed55f13" href="/docs/integrations/overview" width="24" height="24" data-path="icons/link.svg">
    Browse every data source and agent tool.
  </Card>
</CardGroup>
