Plugins

Note: The plugin API is a work in progress and will likely change in the future.

For most use-cases, Insomnia’s core feature set will suffice. However, for certain things like custom authentication mechanisms or complex workflows, more advanced behavior may be required.

This document provides an overview of Insomnia’s plugin APIs, which can be used to extend the functionality of Insomnia.

Index

Introduction

There are two general types of plugins that you can create for Insomnia. A plugin can either add a custom template tag for rendering custom values, or defined a hook which can do things like intercept requests and responses to add custom behavior.

Create a Plugin

A plugin is a NodeJS Module that is placed in a specific directory that Insomnia knows about.

  • MacOS: ~/Library/Application\ Support/Insomnia/plugins/
  • Windows: %APPDATA%\Insomnia\plugins\
  • Linux: $XDG_CONFIG_HOME/Insomnia/plugins/ or ~/.config/Insomnia/plugins/

A plugin directory requires at least two files:

base64/             
 ├── package.json   # Node module metadata
 └── *.js           # One or more JavaScript files

The package.json must contain an insomnia attribute to be identified as a plugin.

Take a look at the following file to see what a minimal package.json should look like.

Note: If you publish an Insomnia plugin to npm, please prefix the name with insomnia-plugin-

Example: Plugin package.json file
{
  "name": "insomna-plugin-base64",  // Npm module name
  "version": "1.0.0",               // Plugin version
  "main": "plugin.js",              // Entry point
  
  /**
   * Insomnia-specific metadata. Without this, Insomnia
   * won't recognize the module as a plugin.
   */
  "insomnia": {                    
    "name": "base64",      // Internal Insomnia plugin name
    "description": "...",  // Plugin description
  },
  
  // External dependencies are also supported
  "dependencies": [],
  "devDependencies": []
}

Managing Plugins

Plugins can be added from the Plugins tab within the application preferences dialog. They can also be downloaded and installed directly from npm.

Debugging

Navigate to View > Toggle DevTools to open the Chrome Developer Tools. From here, you can debug Insomnia as you would any web project in Chrome.

If you want to focus specifically on the plugin you are developing, you can find it from the Sources tab and/or filter the Console based on the plugin’s file name.

Template Tags

As mentioned, a custom Template Tag can be added, which can then be referenced inside Insomnia’s template system to render custom values.

type RenderContext = {
  // API not finalized yet
};

type TemplateTag = {
  name: string,
  displayName: DisplayName,
  disablePreview?: () => boolean,
  description?: string,
  deprecated?: boolean,
  validate?: (value: any) => ?string,
  priority?: number,
  args: Array<{
    displayName: string,
    description?: string,
    defaultValue: string | number | boolean,
    type: 'string' | 'number' | 'enum' | 'model',
    
    // Only type === 'string'
    placeholder?: string,

    // Only type === 'model'
    modelType: string,

    // Only type === 'enum'
    options: Array<{
      displayName: string,
      value: string,
      description?: string,
      placeholder?: string,
    }>,
  }>,
};
Example: Template tag to generate random number
/**
 * Example template tag that generates a random number 
 * between a user-provided MIN and MAX
 */
module.exports.templateTags = [{
    name: 'random',
    displayName: 'Random Integer',
    description: 'Generate random things',
    args: [
        {
            displayName: 'Minimum',
            description: 'Minimum potential value',
            type: 'number',
            defaultValue: 0
        }, 
        {
            displayName: 'Maximum',
            description: 'Maximum potential value',
            type: 'number',
            defaultValue: 100
        }
    ],
    async run (context, min, max) {
        return Math.round(min + Math.random() * (max - min));
    }
}];

Request/Response Hooks

Plugins can implement “hook” functions that get called when certain things happen. A plugin can currently export two different types of hooks:

type RequestContext = {
    app: AppContext,            // Defined Below
    request: RequestContext     // Defined Below
};

type ResponseContext = {
    app: AppContext,            // Defined Below
    response: ResponseContext   // Defined below
}

// Hooks are exported as an array of "hook" functions which get 
// called with the appropriate plugin API context.
module.exports.requestHooks = Array<(context: RequestContext) => void]
module.exports.responseHooks = Array<(context: ResponseContext) => void]

Folder Actions

Actions can be added to the bottom of the folder dialog by setting

type RequestGroupAction = {
    label: string,
    action: (context: Context, { 
        requestGroup: RequestGroup, 
        requests: Array<Request>
    }): Promise<void>
};

// Folder actions are exported as an array of objects
module.exports.requestHooks = Array<RequestGroupAction>
Example: Plugin to send all requests in a folder

module.exports.requestGroupActions = [
  {
    label: 'Send Requests',
    action: async (context, data) => {
      const { requests } = data;

      let results = [];
      for (const request of requests) {
        const response = await context.network.sendRequest(request);
        results.push(`<li>${request.name}: ${response.statusCode}</li>`);
      }

      const html = `<ul>${results.join('\n')}</ul>`;

      context.app.showGenericModalDialog('Results', { html });
    },
  },
];

context.request

// context.request functions
type RequestContext = {
    getId (): string,
    getName (): string,
    getUrl (): string,
    setUrl (url: string): void,
    getMethod (): string,
    getHeader (name: string): string | null, 
    hasHeader (name: string): boolean,
    removeHeader (name: string): void,
    setHeader (name: string, value: string): void,
    addHeader (name: string, value: string): void,
    getParameter (name: string): string | null,
    getParameters (): Array<{name: string, value: string}>,
    setParameter (name: string, value: string): void,
    hasParameter (name: string): boolean,
    addParameter (name: string, value: string): void,
    removeParameter (name: string): void,
    setBodyText (text: string): void,
    getBodyText (): string,
    setCookie (name: string, value: string): void,
    getEnvironmentVariable (name: string): any,
    getEnvironment (): Object,
    setAuthenticationParameter (string: any): void,
    getAuthentication (): Object,
    setCookie (name: string, value: string): void,
    settingSendCookies (enabled: boolean): void,
    settingStoreCookies (enabled: boolean): void,
    settingEncodeUrl (enabled: boolean): void,
    settingDisableRenderRequestBody (enabled: boolean): void,
};
Example: Set Content-Type header on every POST request
// Request hook to set header on every request
module.exports.requestHooks = [
  context => {
    if (context.request.getMethod().toUpperCase() === 'POST') {
      context.request.setHeader('Content-Type', 'application/json');
    }
  }
];

context.response

// context.response functions
getRequestId (): string;
getStatusCode (): number
getStatusMessage (): string
getBytesRead (): number
getTime (): number
getBody (): Buffer | null
getHeader (name: string): string | Array<string> | null
hasHeader (name: string): boolean
Example: Save response to file
const fs = require('fs');

// Request hook to save response to file
module.exports.responseHooks = [
  context => {
   context.response.getBodyStream().pipe(
      fs.createWriteStream('/Users/gschier/Desktop/response-body.txt')
    );
  }
];

context.store

Plugins can store persistent data via the storage context. Data is only accessible to the plugin that stored it.

// context.store functions
async hasItem(key: string): Promise<boolean>
async setItem(key: string, value: string): Promise<void>
async getItem(key: string): Promise<string | null>
async removeItem(key: string): Promise<void>
async clear(): Promise<void>
async all(): Promise<Array<{ key: string, value: string }>>

context.app

The app context contains a general set of helpers that are global to the application.

// context.app functions
alert(title: string, message?: string): Promise<void>
prompt(title: string, options?: {
    label?: string,
    defaultValue?: string,
    submitName?: string,
    cancelable?: boolean,
  }): Promise<string>
getPath(name: 'desktop'): string
async showSaveDialog(options: { defaultPath?: string } = {}): Promise<string | null>

context.data

The data context contains helpers related to importing and exporting Insomnia workspaces.

// context.data.import functions
async uri(uri: string, options: { workspaceId?: string } = {}): Promise<void>
async raw(text: string, options: { workspaceId?: string } = {}): Promise<void>

// context.data.export functions
async insomnia(options: { 
    includePrivate?: boolean,
    format?: 'json' | 'yaml'
  }): Promise<string>
async har(options: { includePrivate?: boolean } = {}): Promise<string><br>

context.network

The network context contains helpers related to sending network requests.

// context.network functions
async sendRequest(request: Request): Promise<Response>