npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

canny-js-api

v1.0.18

Published

API wrapper library for Canny

Downloads

7

Readme

canny-js-api

API wrapper library for canny.io

CJS and ESM

This documentation is written assuming that you will use ESM modules. However, CommonJS modules are supported. The difference in syntax is

ESM

import { setApiKey } from "canny-js-api";

CJS

const { setApiKey } = require("canny-js-api");

Getting Started

To get started with the API, set your canny API Key

import { setApiKey } from "canny-js-api";

setApiKey("thisismykey");

API Call return values

All API calls return an async result value, which contains a success boolean. If the value of success is true, then the result also contains a value property which contains the body of the response from Canny. If the success value is false, then the result also contains an error property which is an instance of Error.

This library uses got (or more specifically got-cjs) to make web requests. If there is an error returned from the API, this should be wrapped in the HTTPError type from the got package. Any other error during the process will be returned as a FailedFetchError.

API Methods

For the full API documentation, refer to the Canny.io API Reference.

Retrieve Board

Reference: https://developers.canny.io/api-reference#retrieve_board

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.retrieveBoard("some-board-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Board", result.value);
})();

List All Boards

Reference: https://developers.canny.io/api-reference#list_all_boards

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listAllBoards();

  if (!result.success) {
    throw result.error;
  }

  console.log("Boards", result.value.boards);
})();

Retrieve Category

Reference: https://developers.canny.io/api-reference#retrieve_category

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.retrieveCategory("some-category-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Category", result.value);
})();

List Categories

Reference: https://developers.canny.io/api-reference#list_categories

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listCategories({
    // Optional
    boardID: "some-board-id",
    limit: 100,
    skip: 10,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("List of categories", result.value.categories);
  console.log("Has more categories", result.value.hasMore);
})();

Create Category

Reference: https://developers.canny.io/api-reference#create_category

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.createCategory({
    // Required
    boardID: "some-board-id",
    name: "My New Category",
    subscribeAdmins: true,

    // Optional
    parentID: "some-parent-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("New Category ID", result.value.id);
})();

Delete Category

Reference: https://developers.canny.io/api-reference#delete_category

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.deleteCategory("some-category-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Success");
})();

Create Changelog Entry

Reference: https://developers.canny.io/api-reference#create_entry

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.createChangelogEntry({
    // Required
    title: "new changelog entry",
    details: "the details of this entry",

    // Optional
    type: "new",
    published: false,
    scheduledFor: "2023-12-12T00:00:00.000Z",
    labelIDs: ["label1", "label2"],
    postIDs: ["post-id-1", "post-id-2"],
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("New Changelog Entry ID", result.value.id);
})();

List Changelog Entries

Reference: https://developers.canny.io/api-reference#list_entries

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listChangelogEntries({
    // Optional
    labelIDs: ["label1", "label2"],
    limit: 100,
    skip: 10,
    sort: "nonPublishedFirst",
    type: "new",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Changelog Entries", result.value.entries);
  console.log("Has more entries", result.value.hasMore);
})();

Retrieve Comment

Reference: https://developers.canny.io/api-reference#retrieve_comment

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listChangelogEntries("some-comment-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Comment", result.value);
})();

List Comments

Reference: https://developers.canny.io/api-reference#list_comments

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listComments({
    // Optional
    authorID: "some-author-id",
    boardID: "some-board-id",
    companyID: "some-company-id",
    limit: 100,
    postID: "some-post-id",
    skip: 10,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Comments", result.value.comments);
  console.log("Has more comments", result.value.hasMore);
})();

Create Comment

Reference: https://developers.canny.io/api-reference#create_comment

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.createComment({
    // Required
    authorID: "some-author-id",
    postID: "some-post-id",
    value: "this is the actual comment",

    // Optional
    imageURLs: ["https://img.example.com/1.png"],
    internal: true,
    parentID: "some-parent-id",
    shouldNotifyVoters: false,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("New Comment ID", result.value.id);
})();

Delete Comment

Reference: https://developers.canny.io/api-reference#delete_comment

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.deleteComment("some-comment-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Success");
})();

List Companies

Reference: https://developers.canny.io/api-reference#list_companies

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listCompanies({
    // Optional
    search: "search string",
    segment: "example.com",
    limit: 100,
    skip: 10,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Companies", result.value.companies);
  console.log("Has more companies", result.value.hasMore);
})();

Update Company

Reference: https://developers.canny.io/api-reference#update_company

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.updateCompany({
    // Required
    id: "some-company-id",
    name: "Company Name",

    // Optional
    created: "2023-01-01T00:00:00.000Z",
    customFields: {
      number: 1,
      string: "2",
      boolean: false,
    },
    monthlySpend: 400.3,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Company ID", result.value.id);
})();

Delete Company

Reference: https://developers.canny.io/api-reference#delete_company

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.deleteCompany("some-company-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Success");
})();

List Opportunities

Reference: https://developers.canny.io/api-reference#list_opportunities

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listOpportunities({
    // Optional
    limit: 100,
    skip: 10,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Opportunities", result.value.opportunities);
  console.log("Has more opportunities", result.value.hasMore);
})();

Retrieve Post

Reference: https://developers.canny.io/api-reference#list_posts

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

// By ID
(async function () {
  const result = await canny.retrievePost({
    // Required
    id: "some-post-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Post", result.value);
})();

// By URL Name
(async function () {
  const result = await canny.retrievePost({
    // Required
    boardID: "some-board-id",
    urlName: "example.com",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Post", result.value);
})();

List Posts

Reference: https://developers.canny.io/api-reference#list_posts

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listPosts({
    // Optional
    boardID: 'some-board-id',
    authorID: 'some-author-id',
    companyID: 'some-company-id',
    tagIDs: ['tag-1-id', 'tag-2-id']
    limit: 100,
    search: 'some search string',
    skip: 10,
    sort: 'newest',
    status: 'open,under,review,planned,in progress'
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Posts", result.value.posts);
  console.log("Has more posts", result.value.hasMore);
})();

Create Post

Reference: https://developers.canny.io/api-reference#create_post

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.createPost({
    // Required
    authorID: "some-author-id",
    boardID: "some-board-id",
    details: "the details of the post",
    title: "the title of the post",

    // Optional
    byID: "some-admin-id",
    categoryID: "some-category-id",
    eta: "12/2023",
    etaPublic: true,
    ownerID: "some-owner-id",
    imageURLs: ["https://img.example.com/1.png"],
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("New Post ID", result.value.id);
})();

Change Post Category

Reference: https://developers.canny.io/api-reference#change_post_category

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.changePostCategory({
    // Required
    postID: "some-post-id",

    // Optional
    categoryID: "some-category-id", // Can be null to remove category
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Updated Post", result.value);
})();

Change Post Status

Reference: https://developers.canny.io/api-reference#change_post_status

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.changePostStatus({
    // Required
    changerID: "some-admin-id",
    postID: "some-post-id",
    shouldNotifyVoters: true,
    status: "open",
    commentValue: "a comment about this status change",
    commentImageURLs: ["https://img.example.com/1.png"],
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Updated Post", result.value);
})();

Add Post Tag

Reference: https://developers.canny.io/api-reference#add_tag

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.addPostTag({
    // Required
    postID: "some-post-id",
    tagID: "some-tag-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Updated Post", result.value);
})();

Remove Post Tag

Reference: https://developers.canny.io/api-reference#remove_tag

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.removePostTag({
    // Required
    postID: "some-post-id",
    tagID: "some-tag-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Updated Post", result.value);
})();

Update Post

Reference: https://developers.canny.io/api-reference#update_post

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.updatePost({
    // Required
    postID: "some-post-id",

    // Optional
    customFields: {
      number: 1,
      string: "2",
      boolean: false,
    },
    details: "the details of the post",
    eta: "12/2023",
    etaPublic: true,
    title: "The title of the post",
    imageURLs: ["https://img.example.com/1.png"],
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Success");
})();

List Status Changes

Reference: https://developers.canny.io/api-reference#list_status_changes

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listStatusChanges({
    // Optional
    boardID: "some-board-id",
    limit: 100,
    skip: 10,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Status changes", result.value.statusChanges);
  console.log("Has more status changes", result.value.hasMore);
})();

Retrieve Tag

Reference: https://developers.canny.io/api-reference#retrieve_tag

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

// By ID
(async function () {
  const result = await canny.retrieveTag("some-tag-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Tag", result.value);
})();

List Tags

Reference: https://developers.canny.io/api-reference#create_tag

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listTags({
    // Optional
    boardID: "some-board-id",
    limit: 100,
    skip: 10,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Tags", result.value.tags);
  console.log("Has more tags", result.value.hasMore);
})();

Create Tag

Reference: https://developers.canny.io/api-reference#create_tag

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.createTag({
    // Required
    boardID: "some-board-id",
    name: "A tag name",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("New Tag", result.value);
})();

List Users

Reference: https://developers.canny.io/api-reference#list_users

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listUsers({
    // Optional
    limit: 100,
    skip: 10,
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Users", result.value);
})();

Retrieve User

Reference: https://developers.canny.io/api-reference#retrieve_user

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

// By Email
(async function () {
  const result = await canny.retrieveUser({
    // Required
    email: "[email protected]",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("User", result.value);
})();

// By ID
(async function () {
  const result = await canny.retrieveUser({
    // Required
    id: "some-user-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("User", result.value);
})();

// By user ID
(async function () {
  const result = await canny.retrieveUser({
    // Required
    userID: "some-external-user-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("User", result.value);
})();

Create or Update User

Reference: https://developers.canny.io/api-reference#create_or_update_user

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.createOrUpdateUser({
    // Required
    userID: "some-user-id",
    name: 'Test Example'

    // Optional
    avatarURL: "https://img.example.com/1.png",
    companies: [
      {
        created: "2020-01-23T04:56:07.890Z",
        customFields: {
          field1: "value1",
          field2: "value2"
        },
        id: "company123",
        monthlySpend: 500.00,
        name: "company name"
      }
    ],
    created: '2023-01-01T00:00:00.000Z',
    customFields: {
      number: 1,
      string: '2',
      boolean: false
    },
    email: '[email protected]'
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Updated user ID", result.value.id);
})();

Delete User

Reference: https://developers.canny.io/api-reference#delete_user

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.deleteUser("some-user-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Success");
})();

Retrieve Vote

Reference: https://developers.canny.io/api-reference#retrieve_vote

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.retrieveVote("some-vote-id");

  if (!result.success) {
    throw result.error;
  }

  console.log("Vote", result.value);
})();

List Votes

Reference: https://developers.canny.io/api-reference#list_votes

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.listVotes({
    // Optional
    boardID: "some-board-id",
    companyID: "some-company-id",
    limit: 100,
    postID: "some-post-id",
    skip: 10,
    userID: "some-user-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Votes", result.value.votes);
  console.log("Has more votes", result.value.hasMore);
})();

Create Vote

Reference: https://developers.canny.io/api-reference#create_vote

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.createVote({
    // Required
    postID: "some-post-id",
    voterID: "some-user-id",

    // Optional
    byId: "some-user-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Success");
})();

Delete vote

Reference: https://developers.canny.io/api-reference#delete_vote

import * as canny from "canny-js-api";

canny.setApiKey("{MY_API_KEY}");

(async function () {
  const result = await canny.deleteVote({
    // Required
    postID: "some-post-id",
    voterID: "some-user-id",
  });

  if (!result.success) {
    throw result.error;
  }

  console.log("Success");
})();