Plugins | Settings
Give Feedback


Updated on September 21, 2021

Plugins can store their website user settings via the REST API, and retrieve them later on. Those settings are submitted by users or plugins to the API, and validated with a schema.

What Are Plugin Settings?

Storing settings directly on Crisp systems, instead of relying on a local database, makes plugins extremely easy to build. A few lines of code, coupled with our API Libraries, can get you very far.

Settings schemas are built with JSON Schema, which let you easily restrict the types of each JSON key, their syntax with regular expressions, and much more.

Each website subscribed to your plugin has its own private settings. Your integration can acquire those settings (for each website), when it starts, or when a new website is subscribed (or settings get updated).

Your integration can also update those settings, for each subscribed website.

Note that settings can be updated by a Crisp user (directly from the Crisp Dashboard), or an integration (directly from the REST API). Some plugins may not update settings from the backend, but let the front-end interface do this from the Crisp Dashboard.

Manage Website Settings

Retrieve settings

Settings for each website should be retrieved when your plugin first starts, or when a plugin just subscribed to your plugin.

You should keep those settings in-memory, loading them once for each website. It is sub-optimal to load the settings from the REST API every single time you need them, and will result in your daily request quota on your REST API token to be over-used.

1. Retrieve settings on start

Upon starting the plugin, you should load up the settings of each website that is subscribed to your plugin.

Using the go-crisp-api library (from the API Libraries guide, also make sure to follow the Quickstart guide), this gives:

// (Make sure that the client variable is set there)

func LoadWebsitesOnStart() {
  var pageNumber uint

  pageNumber = 0
  resultCounter := -1

  for resultCounter != 0 {
    resultCounter = 0

    // Configure this to either 'true' or 'false' if you need to return settings for non-configured plugins as well
    configured = true

    websites, _, err := client.Plugin.ListAllConnectWebsites(pageNumber, configured)

    if err == nil {
      fmt.Printf("Loaded page #%d of website results (%d websites)", pageNumber, len(*websites))

      for _, websiteItem := range *websites {

        // Here: store the website settings in-memory with: websiteItem.WebsiteID and websiteItem.Settings
    } else {
      fmt.Printf("Could not list bound websites because: %+v", err)

2. Refresh local settings whenever they get updated

Once your plugin is started, you need to schedule a background settings refresh, for the plugins that have just subscribed to your plugin, or updated their settings. This will also give you a chance to clear out the websites that unsubscribed as well.

Using the go-crisp-api library, this gives:

func ScheduleMaintainWebsites() {
  fmt.Printf("Scheduled websites maintain")

  lastCheckTime := time.Now()

  for {
    // Check for settings changes every 20 seconds
    // You may adjust this, but note that this counts against your daily quota
    time.Sleep(20 * time.Second)

    err := TickMaintainWebsites(lastCheckTime)

    // If refresh failed, dont bump last check time to re-schedule it later.
    // This avoids losing some ops in the wild.
    if err == nil {
      lastCheckTime = time.Now()

func TickMaintainWebsites(lastCheckTime time.Time) (error) {
  // List websites differential
  fmt.Printf("Fetching websites maintain list since: %d", lastCheckTime)

  // Configure this to either 'true' or 'false' if you need to return settings for non-configured plugins as well
  configured = true

  websites, _, err := client.Plugin.ListConnectWebsitesSince(lastCheckTime, configured)

  if err == nil {
    countResults := len(*websites)

    if countResults > 0 {
      fmt.Printf("Fetched websites maintain list with changes (%d websites)", countResults)

      for _, websiteItem := range *websites {
        switch *websiteItem.Difference {
        case "added":
          // Here: store the website settings in-memory with: websiteItem.WebsiteID and websiteItem.Settings

        case "updated":
          // Here: update the website settings in-memory with: websiteItem.WebsiteID and websiteItem.Settings

        case "removed":
          // Here: remove the website settings from memory
    } else {
      fmt.Printf("Fetched websites maintain list without changes")
  } else {
    fmt.Printf("Could not fetch websites maintain list because: %+v", err)

  return err

Now, at the end of the LoadWebsitesOnStart() method, add:

func LoadWebsitesOnStart() {
  // <previous code eluded>

  // Maintain list of websites up to date in time
  // Important: start this in a Goroutine
  go ScheduleMaintainWebsites()
Note that ScheduleMaintainWebsites() should be called after the initial LoadWebsitesOnStart() of settings has completed. It must be called in a Goroutine background task, as not to block e the main thread.
You could, alternatively, listen for the plugin:settings:saved event from the RTM API, and avoid polling the REST API for settings updates too frequently. However, this will not provide you with a list of websites that uninstalled your plugin, therefore you would need to keep polling, but much less frequently, eg. every 10 minute (for cleanup purposes).

Update settings

Whenever settings need to be updated for a given website, you may re-submitted them to the REST API, as a single JSON object.

Make sure that the settings submitted are valid against your settings schema, otherwise the REST API will reject your save request with an error.

Using the go-crisp-api library, this gives:

// This structure contains example settings keys that map to JSON
// Adjust it with your own settings structure
type pluginSettings struct {
  AccessToken   string  `json:"access_token"`
  EnableAlerts  bool    `json:"enable_alerts"`

func CommitPluginSettings(pluginID string, websiteID string, settings pluginSettings) (error) {
  fmt.Printf("Saving plugin settings for website: %s with data: %+v", websiteID, settings)

  // Commit subscription settings
  // You need to pass your Plugin ID, as well as Website ID there
  _, err := client.Plugin.SaveSubscriptionSettings(websiteID, pluginID, settings)

  if err != nil {
    fmt.Printf("Failed saving plugin settings for website: %s with data: %+v, because: %s", websiteID, settings, err)

  return err
After updating a website settings by calling this function, you could either mutate the object storing all subscribed website settings immediately, or rely on the next TickMaintainWebsites() call that will occur to refresh the settings. For most integrations, waiting for the next REST API poll request is probably more convenient and less error-prone.

Settings Schemas

Settings schema let the REST API validate settings data that either users or your plugin attempt to save. The settings schema is pre-configured in advance, and is defined using JSON Schema.

Settings schema examples

An in-depth guide page is dedicated to providing plugin settings schema examples. You may read this guide on Examples.

Validating my schema

Before you can save your schema in the Marketplace, you need to make sure they are valid against the JSON Schema specification.

The Marketplace lets you do this easily:

  1. Go to the Crisp Marketplace;
  2. Select your plugin, and go to the Settings tab;
  3. In the Settings section, enter your schema data;
  4. Hit the Test Settings button;
  5. Your schema may either be confirmed as valid, or invalid (we provide an explanation of what's wrong in this case);
Enter your settings schema, and hit the test button
This is what you see when your schema is valid
This is what you see when your schema is invalid

Configuring the plugin schema

After you validated your plugin schema from the Marketplace, the Save Settings button becomes clickable.

Simply click on the Save Settings button. Once saved, scroll up and create a new Submission in the notification that shows.