# Canny Source

<p><a href="https://canny.io/" >Canny</a> is a customer feedback management tool which captures, organizes, and analyzes product feedback in one place to help you make informed product decisions.</p>
<p>This guide will help you set up Canny as a source in RudderStack.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="get-started">Get started</h2><ol>
<li>Go to your <a href="https://app.rudderstack.com/" >RudderStack dashboard</a> and click <strong>Add Source</strong>. From the list of <strong>Event Streams</strong> sources, select <strong>Canny</strong>.</li>
<li>Assign a name to your source and click <strong>Continue</strong>.</li>
<li>Your Canny source is now configured. Go to the <strong>Settings</strong> tab of the source and note the <strong>Webhook URL</strong>:</li>
</ol>

<figure class="image--main "  >
    <a 
         href="/docs/images/event-stream-sources/source-webhook-url.webp"
        
        >
        <img src="/docs/images/event-stream-sources/source-webhook-url.webp" 
         alt="Canny source webhook URL"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<ol start="4">
<li>Log in to your <a href="https://canny.io/login" >Canny account</a>. In the top-right side, select the <strong>Settings</strong> option under your profile followed by <strong>API &amp; Webhooks</strong>.</li>
<li>Enter the <strong>Webhook URL</strong> under <strong>Webhooks</strong> section:</li>
</ol>

<figure class="image--main "  >
    <a 
         href="/docs/images/event-stream-sources/webhook-url-canny.webp"
        
        >
        <img src="/docs/images/event-stream-sources/webhook-url-canny.webp" 
         alt="Canny source webhook URL"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<ol start="6">
<li>Click <strong>Add</strong>.</li>
</ol>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="event-transformation">Event transformation</h2><p>RudderStack ingests the Canny events after converting them into the RudderStack event format. It also maps the following properties from the Canny event payload to the RudderStack properties:</p>
<table>
  <thead>
      <tr>
          <th>Canny property</th>
          <th>RudderStack property</th>
          <th>Notes</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>created</code></td>
          <td><code>timestamp</code>,<code>originalTimestamp</code></td>
          <td>-</td>
      </tr>
      <tr>
          <td><code>object</code></td>
          <td><code>properties</code></td>
          <td>RudderStack excludes <code>author</code>/<code>voter</code> from the properties.</td>
      </tr>
      <tr>
          <td><code>objectType</code></td>
          <td><code>properties.objectType</code></td>
          <td>-</td>
      </tr>
      <tr>
          <td><code>type</code></td>
          <td><code>event</code></td>
          <td>-</td>
      </tr>
      <tr>
          <td><code>object.author</code></td>
          <td><code>context.traits</code></td>
          <td>RudderStack excludes <code>userId</code> and <code>id</code>.</td>
      </tr>
      <tr>
          <td><code>object.author.userId</code></td>
          <td><code>userId</code></td>
          <td>-</td>
      </tr>
      <tr>
          <td>SHA-256 hash of <code>object.author.email</code></td>
          <td><code>anonymousId</code></td>
          <td>Only if <code>userId</code> is not present</td>
      </tr>
      <tr>
          <td>SHA-256 hash of <code>object.voter.email</code></td>
          <td><code>anonymousId</code></td>
          <td>Only if <code>userId</code> is not present <strong>and</strong> <code>type</code> is <code>vote.created</code>/<code>vote.deleted</code></td>
      </tr>
      <tr>
          <td><code>object.voter.userId</code></td>
          <td><code>userId</code></td>
          <td>Only if <code>type</code> is <code>vote.created</code>/<code>vote.deleted</code></td>
      </tr>
      <tr>
          <td><code>object.voter.id</code></td>
          <td><code>context.externalId[0].value</code></td>
          <td>Only if <code>type</code> is <code>vote.created</code>/<code>vote.deleted</code></td>
      </tr>
      <tr>
          <td><code>cannyUserId</code></td>
          <td><code>context.externalId[0].type</code></td>
          <td>-</td>
      </tr>
      <tr>
          <td><code>object.author.id</code></td>
          <td><code>context.externalId[0].id</code></td>
          <td>-</td>
      </tr>
  </tbody>
</table>
<p>Canny supports ingesting the following events:</p>
<table>
  <thead>
      <tr>
          <th>Canny events</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>post.created</code></td>
          <td>Occurs when a new post is created.</td>
      </tr>
      <tr>
          <td><code>post.deleted</code></td>
          <td>Occurs when a post is deleted.</td>
      </tr>
      <tr>
          <td><code>post.jira_issue_linked</code></td>
          <td>Occurs when a Jira issue is linked to a post.</td>
      </tr>
      <tr>
          <td><code>post.jira_issue_unlinked</code></td>
          <td>Occurs when a Jira issue is unlinked from a post.</td>
      </tr>
      <tr>
          <td><code>post.status_changed</code></td>
          <td>Occurs when a post&rsquo;s status is changed.</td>
      </tr>
      <tr>
          <td><code>comment.created</code></td>
          <td>Occurs when a new comment is created.</td>
      </tr>
      <tr>
          <td><code>comment.deleted</code></td>
          <td>Occurs when a comment is deleted.</td>
      </tr>
      <tr>
          <td><code>vote.created</code></td>
          <td>Occurs when a user votes on a post.</td>
      </tr>
      <tr>
          <td><code>vote.deleted</code></td>
          <td>Occurs when a user unvotes on a post.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="how-rudderstack-creates-the-event-payload">How RudderStack creates the event payload</h2><p>This section details how RudderStack receives the data from Canny source and creates the resulting payload.</p>
<p>A sample payload sent by Canny is shown below:</p>
<div class="rs-code">
  <div class="rs-code__head">json<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-json" data-lang="json">{
    &#34;created&#34;: &#34;2022-07-28T10:52:46.294Z&#34;,
    &#34;object&#34;: {
        &#34;author&#34;: {
            &#34;created&#34;: &#34;2022-07-15T11:16:32.648Z&#34;,
            &#34;email&#34;: &#34;alex@example.com&#34;,
            &#34;id&#34;: &#34;1hKOmRA4el9Zt1WSfVJIVo4GRlm&#34;,
            &#34;isAdmin&#34;: true,
            &#34;name&#34;: &#34;Alex Keener&#34;,
            &#34;url&#34;: &#34;https://rudder.canny.io/admin/users/alex-keener&#34;,
            &#34;userID&#34;: null
        },
        &#34;board&#34;: {
            &#34;created&#34;: &#34;2022-07-25T12:11:19.895Z&#34;,
            &#34;id&#34;: &#34;VJIVo4GRlm&#34;,
            &#34;name&#34;: &#34;features&#34;,
            &#34;postCount&#34;: 13,
            &#34;url&#34;: &#34;https://rudder.canny.io/admin/board/features&#34;
        },
        &#34;by&#34;: null,
        &#34;category&#34;: null,
        &#34;commentCount&#34;: 0,
        &#34;created&#34;: &#34;2022-07-28T10:52:46.172Z&#34;,
        &#34;customFields&#34;: [{
            &#34;id&#34;: &#34;62e1382&#34;,
            &#34;name&#34;: &#34;John&#34;,
            &#34;value&#34;: &#34;123&#34;
        }],
        &#34;details&#34;: &#34;Array of images&#34;,
        &#34;eta&#34;: null,
        &#34;id&#34;: &#34;62e26a&#34;,
        &#34;imageURLs&#34;: [
            &#34;https://canny.io/images/6371453a825c79351c52a6063c3af476.jpg&#34;,
            &#34;https://canny.io/images/47db6ee5035bfb45ea87a74f2eb17928.jpg&#34;
        ],
        &#34;owner&#34;: null,
        &#34;score&#34;: 1,
        &#34;status&#34;: &#34;open&#34;,
        &#34;tags&#34;: [],
        &#34;title&#34;: &#34;Custom Fields Testing&#34;,
        &#34;url&#34;: &#34;https://rudder.canny.io/admin/board/features/p/custom-fields-testing&#34;
    },
    &#34;objectType&#34;: &#34;post&#34;,
    &#34;type&#34;: &#34;post.created&#34;
}</code></pre></div>
</div>
<p>RudderStack transforms the above payload into the following payload:</p>
<div class="rs-code">
  <div class="rs-code__head">json<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-json" data-lang="json">{
    &#34;anonymousId&#34;: &#34;d6a9d06e8a464324d448003ff0467d971a55ca2950e11fc51faaec4e2850ecc6&#34;,
    &#34;event&#34;: &#34;post.created&#34;,
    &#34;integrations&#34;: {
        &#34;Canny&#34;: false
    },
    &#34;context&#34;: {
        &#34;library&#34;: {
            &#34;name&#34;: &#34;unknown&#34;,
            &#34;version&#34;: &#34;unknown&#34;
        },
        &#34;integration&#34;: {
            &#34;name&#34;: &#34;Canny&#34;,
            &#34;version&#34;: &#34;1.0.0&#34;
        },
        &#34;traits&#34;: {
        &#34;created&#34;: &#34;2022-07-15T11:16:32.648Z&#34;,
        &#34;email&#34;: &#34;alex@example.com&#34;,
        &#34;isAdmin&#34;: true,
        &#34;name&#34;: &#34;Alexx Keener&#34;,
        &#34;url&#34;: &#34;https://rudder.canny.io/admin/users/alex-keener&#34;
      },
        &#34;externalId&#34;: [{
            &#34;type&#34;: &#34;cannyUserId&#34;,
            &#34;id&#34;: &#34;1hKOmRA4el9Zt1WSfVJIVo4GRlm&#34;
        }]
    },
    &#34;timestamp&#34;: &#34;2022-07-28T10:52:46.294Z&#34;,
    &#34;originalTimestamp&#34;: &#34;2022-07-28T10:52:46.294Z&#34;,
    &#34;type&#34;: &#34;track&#34;,
    &#34;properties&#34;: {
        &#34;board&#34;: {
            &#34;created&#34;: &#34;2022-07-25T12:11:19.895Z&#34;,
            &#34;id&#34;: &#34;VJIVo4GRlm&#34;,
            &#34;name&#34;: &#34;features&#34;,
            &#34;postCount&#34;: 13,
            &#34;url&#34;: &#34;https://rudder.canny.io/admin/board/features&#34;
        },
        &#34;by&#34;: null,
        &#34;category&#34;: null,
        &#34;commentCount&#34;: 0,
        &#34;created&#34;: &#34;2022-07-28T10:52:46.172Z&#34;,
        &#34;customFields&#34;: [{
            &#34;id&#34;: &#34;62e1382&#34;,
            &#34;name&#34;: &#34;abc&#34;,
            &#34;value&#34;: &#34;123&#34;
        }],
        &#34;details&#34;: &#34;Array of images&#34;,
        &#34;eta&#34;: null,
        &#34;id&#34;: &#34;62e26a&#34;,
        &#34;imageURLs&#34;: [
            &#34;https://canny.io/images/6371453a825c79351c52a6063c3af476.jpg&#34;,
            &#34;https://canny.io/images/47db6ee5035bfb45ea87a74f2eb17928.jpg&#34;
        ],
        &#34;objectType&#34;: &#34;post&#34;,
        &#34;owner&#34;: null,
        &#34;score&#34;: 1,
        &#34;status&#34;: &#34;open&#34;,
        &#34;tags&#34;: [],
        &#34;title&#34;: &#34;Custom Fields Testing&#34;,
        &#34;url&#34;: &#34;https://rudder.canny.io/admin/board/features/p/custom-fields-testing&#34;
    }
}</code></pre></div>
</div>

