Plugin Development

Plugin Reference

Complete reference for creating JSON-based plugins in Invoice Radar

Overview

Invoice Radar plugins are defined using JSON configuration files that specify how to authenticate with a service and extract documents. This reference covers the complete plugin structure and configuration options.

Plugin Structure

A plugin consists of several main sections:

{
  "$schema": "https://raw.githubusercontent.com/invoiceradar/plugins/main/schema.json",
  "id": "example-service",
  "name": "Example Service",
  "description": "Short description of the Example Service",
  "homepage": "https://example.com",
  "autofill": true,
  "configSchema": {
    // Configuration options
  },
  "startAuth": [
    // Authentication steps
  ],
  "checkAuth": [
    // Authentication verification steps
  ],
  "getConfigOptions": [
    // Optional: Extract configuration options
  ],
  "getDocuments": [
    // Document extraction steps
  ]
}

Core Properties

Basic Metadata

PropertyTypeRequiredDescription
$schemastringNoURL to the JSON schema for validation
idstringYesUnique identifier for the plugin
namestringYesDisplay name of the plugin
descriptionstringNoBrief description of what the plugin does
homepagestringNoURL of the service (used for logo and linking)

Configuration Schema

Define user-configurable options using the configSchema property:

{
  "configSchema": {
    "teamId": {
      "type": "string",
      "title": "Team ID",
      "description": "The ID of your team",
      "required": true,
      "example": "team_abc123"
    },
    "apiKey": {
      "type": "password",
      "title": "API Key",
      "description": "Your API key for authentication",
      "required": true
    },
    "environment": {
      "type": "string",
      "title": "Environment",
      "description": "Select the environment",
      "options": [
        { "value": "production", "label": "Production" },
        { "value": "staging", "label": "Staging" }
      ],
      "default": "production"
    },
    "downloadReceipts": {
      "type": "boolean",
      "title": "Download Receipts",
      "description": "Download receipts for each invoice",
      "default": false
    }
  }
}

Configuration Property Types

TypeTypeScript TypeDescription
stringstringText input field
passwordstringPassword input field (masked)
numbernumberNumeric input field
booleanbooleanCheckbox input

Configuration Property Options

PropertyTypeDescription
titlestringDisplay label for the field
descriptionstringHelp text explaining the field
requiredbooleanWhether the field is required
defaultstring | number | booleanDefault value
examplestringExample value to show users
hiddenbooleanHide the field from users
optionsArray<{value: string, label: string}>Dropdown options

Plugin Flows

Authentication Flow (startAuth)

Steps to authenticate a user who isn't logged in:

{
  "startAuth": [
    {
      "action": "navigate",
      "url": "https://example.com/login"
    },
    {
      "action": "waitForElement",
      "selector": "#login-form"
    }
  ]
}

Authentication Check (checkAuth)

Steps to verify if a user is already authenticated:

{
  "checkAuth": [
    {
      "action": "navigate",
      "url": "https://example.com/dashboard"
    },
    {
      "action": "checkElementExists",
      "selector": "#user-menu"
    }
  ]
}

Configuration Options (getConfigOptions)

Optional steps to extract configuration options like team IDs or project lists. These will be exposed to the user as a dropdown in the configuration modal.

{
  "configSchema": {
    "teamId": {
      "type": "string",
      "title": "Team ID",
      "description": "The ID of your team",
      "required": true,
      "example": "team_abc123"
    }
  },
  "getConfigOptions": [
    {
      "action": "navigate",
      "url": "https://example.com/settings"
    },
    {
      "action": "extractAll",
      "selector": ".team-item",
      "variable": "team",
      "fields": {
        "id": ".team-id",
        "name": ".team-name"
      },
      "forEach": [
        {
          "action": "exposeOption",
          "config": "teamId",
          "option": "{{team}}"
        }
      ]
    }
  ]
}

Document Extraction (getDocuments)

Steps to find and download documents:

{
  "getDocuments": [
    {
      "action": "navigate",
      "url": "https://example.com/invoices"
    },
    {
      "action": "extractAll",
      "selector": ".invoice-row",
      "variable": "invoice",
      "fields": {
        "id": ".invoice-id",
        "date": ".invoice-date",
        "total": ".invoice-total",
        "url": ".download-link[href]"
      },
      "forEach": [
        {
          "action": "downloadPdf",
          "url": "{{invoice.url}}",
          "document": "{{invoice}}"
        }
      ]
    }
  ]
}

Using Configuration Variables

Access user configuration within steps using template syntax:

{
  "action": "navigate",
  "url": "https://example.com/team/{{teamId}}/invoices"
}

Step Reference

For detailed information about available steps, see the Steps Reference documentation.

Autofill Configuration

Invoice Radar automatically detects and fills provided login credentials (username, password, OTP) and submits the authentication form to streamline the login process.

Default Behavior

By default, autofill is set to true, which enables automatic input detection for:

  • Username (also works for email fields)
  • Password
  • OTP (One-Time Password/2FA codes)
  • Submit (automatically submits the form after filling credentials)

When enabled, Invoice Radar will automatically detect and fill these fields during the authentication process, then submit the form to complete the login.

{
  "autofill": true
}

Customization Options

You can customize or disable autofill for individual fields by setting each property (username, password, otp, submit) to either:

  • false - Disables autofill for that specific field
  • Configuration object - Customizes the behavior with these options:
    • selector: Custom CSS selector if the default detection doesn't work
    • title: Custom label for the field in the UI (e.g., "Email" instead of "Username")

Autofill Field Options

FieldTypeDescription
usernameboolean | objectUsername/email field configuration
passwordboolean | objectPassword field configuration
otpboolean | objectOne-time password field configuration
submitboolean | objectSubmit button configuration

Each field can be:

  • true: Enable with automatic detection
  • false: Disable the field
  • object: Custom configuration with selector and optional title

Configuration Examples

Disable Automatic Submission

{
  "autofill": {
    "submit": false
  }
}

Custom Selectors

In case the default autofill doesn't work, you can provide custom selectors for each field.

{
  "autofill": {
    "username": {
      "selector": "#email-input",
      "title": "Email Address"
    },
    "password": {
      "selector": "#password-input"
    },
    "otp": false,
    "submit": {
      "selector": "#login-button"
    }
  }
}

User Agent Override

{
  "userAgentOverride": "Mozilla/5.0 (compatible; CustomBot/1.0)"
}

You can override the browser's user agent string. Set to true to use a default override, or provide a custom string.

Examples

Basic Plugin

{
  "id": "simple-service",
  "name": "Simple Service",
  "description": "Short description of the Simple Service",
  "homepage": "https://simple.com",
  "startAuth": [
    {
      "action": "navigate",
      "url": "https://simple.com/login"
    }
  ],
  "checkAuth": [
    {
      "action": "checkURL",
      "url": "https://simple.com/dashboard"
    }
  ],
  "getDocuments": [
    {
      "action": "navigate",
      "url": "https://simple.com/invoices"
    },
    {
      "action": "extractAll",
      "selector": ".invoice",
      "variable": "invoice",
      "fields": {
        "id": ".id",
        "date": ".date",
        "total": ".total"
      },
      "forEach": [
        {
          "action": "printPdf",
          "document": "{{invoice}}"
        }
      ]
    }
  ]
}

Advanced Plugin with Configuration

{
  "id": "advanced-service",
  "name": "Advanced Service",
  "description": "Extract invoices with team support",
  "homepage": "https://advanced.com",
  "autofill": {
    "username": {
      "title": "Email"
    },
    "submit": {
      "selector": "#sbmt-btn"
    }
  },
  "configSchema": {
    "teamId": {
      "type": "string",
      "title": "Team ID",
      "required": true
    },
    "includeArchived": {
      "type": "boolean",
      "title": "Include Archived Invoices",
      "default": false
    }
  },
  "autofill": {
    "username": {
      "selector": "#email",
      "title": "Email"
    },
    "password": true,
    "otp": false
  },
  "startAuth": [
    {
      "action": "navigate",
      "url": "https://advanced.com/login"
    }
  ],
  "checkAuth": [
    {
      "action": "checkElementExists",
      "selector": "#user-avatar"
    }
  ],
  "getConfigOptions": [
    {
      "action": "extractAll",
      "selector": ".team-option",
      "variable": "team",
      "fields": {
        "value": "[data-team-id]",
        "label": ".team-name"
      },
      "forEach": [
        {
          "action": "exposeOption",
          "config": "teamId",
          "option": "{{team}}"
        }
      ]
    }
  ],
  "getDocuments": [
    {
      "action": "navigate",
      "url": "https://advanced.com/{{teamId}}/invoices"
    },
    {
      "action": "if",
      "script": "'{{includeArchived}}' === 'true'",
      "then": [
        {
          "action": "click",
          "selector": "#include-archived"
        }
      ]
    },
    {
      "action": "extractAll",
      "selector": ".invoice-item",
      "variable": "invoice",
      "fields": {
        "id": ".invoice-number",
        "date": ".invoice-date",
        "total": ".invoice-amount",
        "downloadUrl": ".download-btn[href]"
      },
      "forEach": [
        {
          "action": "downloadPdf",
          "url": "{{invoice.downloadUrl}}",
          "document": {
            "id": "{{invoice.id}}",
            "date": "{{invoice.date}}",
            "total": "{{invoice.total}}"
          }
        }
      ]
    }
  ]
}

Validation

Plugins are validated against the JSON schema. Common validation errors include:

  • Missing required properties (id, name, startAuth, checkAuth, getDocuments)
  • Invalid step configurations
  • Incorrect configuration schema types
  • Missing document properties in PDF download steps

Best Practices

  1. Use descriptive IDs: Choose unique, descriptive plugin IDs
  2. Provide clear descriptions: Help users understand what the service does
  3. Handle errors gracefully: Use optional: true for non-critical steps
  4. Use proper selectors: Prefer stable selectors over brittle ones
  5. Test thoroughly: Verify the plugin works across different scenarios
  6. Document configuration: Provide clear descriptions and examples for config options