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
| Property | Type | Required | Description |
|---|---|---|---|
$schema | string | No | URL to the JSON schema for validation |
id | string | Yes | Unique identifier for the plugin |
name | string | Yes | Display name of the plugin |
description | string | No | Brief description of what the plugin does |
homepage | string | No | URL 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
| Type | TypeScript Type | Description |
|---|---|---|
string | string | Text input field |
password | string | Password input field (masked) |
number | number | Numeric input field |
boolean | boolean | Checkbox input |
Configuration Property Options
| Property | Type | Description |
|---|---|---|
title | string | Display label for the field |
description | string | Help text explaining the field |
required | boolean | Whether the field is required |
default | string | number | boolean | Default value |
example | string | Example value to show users |
hidden | boolean | Hide the field from users |
options | Array<{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 selector (CSS or XPath) if the default detection doesn't work. XPath selectors must start with/,./, or.[title: Custom label for the field in the UI (e.g., "Email" instead of "Username")
Autofill Field Options
| Field | Type | Description |
|---|---|---|
username | boolean | object | Username/email field configuration |
password | boolean | object | Password field configuration |
otp | boolean | object | One-time password field configuration |
submit | boolean | object | Submit button configuration |
Each field can be:
true: Enable with automatic detectionfalse: Disable the fieldobject: Custom configuration withselectorand optionaltitle
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
documentproperties in PDF download steps
Selector Syntax
Invoice Radar supports both CSS selectors and XPath selectors in the selector field:
- CSS selectors (default): Standard CSS syntax like
#id,.class,div > span - XPath selectors: Must start with
/,./, or.[(e.g.,//button[text()='Submit'],.//span[contains(text(), 'Invoice')],.[contains(@class, 'active')])
XPath is particularly useful for selecting elements by their text content, which is not possible with CSS selectors.
Best Practices
- Use descriptive IDs: Choose unique, descriptive plugin IDs
- Provide clear descriptions: Help users understand what the service does
- Handle errors gracefully: Use
optional: truefor non-critical steps - Use proper selectors: Prefer stable selectors over brittle ones. Both CSS and XPath are supported
- Test thoroughly: Verify the plugin works across different scenarios
- Document configuration: Provide clear descriptions and examples for config options