Plugin Development

Steps Reference

Complete reference for all available plugin steps in Invoice Radar

Overview

Steps are the building blocks of Invoice Radar plugins. They define the sequence of actions that the browser automation engine will perform to authenticate with a service, navigate through pages, and extract documents. Each step represents a single action like clicking a button, typing text, or downloading a PDF.

Steps are executed sequentially within each plugin flow (startAuth, checkAuth, getConfigOptions, getDocuments), and support advanced features like conditional logic, loops, and data extraction.

Step Structure

All steps share a common structure with an action property that defines the type of operation. E.g. click, type, navigate, extract, etc.

{
  "action": "click",
  "selector": "#submit-button"
}

Common Properties

Many steps support these common properties:

PropertyTypeDescription
actionstringRequired. The type of step to execute
descriptionstringOptional human-readable description of the step
timeoutnumberTimeout in milliseconds (defaults vary by step)
optionalbooleanWhether the flow should continue if step fails
iframestringTarget a specific iframe (selector or true)

Variables and Templating

Steps support variable interpolation using double curly braces {{variableName}}. Variables can be:

  • Configuration values: Access user settings with {{configKey}}
  • Extracted data: Use data from extract or extractAll steps
  • Built-in variables: Like {{index}} in loops

Defining Variables in Steps

The primary way to dynamically define variables is through the extract and extractAll steps:

  • extract: Creates a single variable from page data or JavaScript execution
  • extractAll: Creates an array of variables by iterating over page elements, with each item available in the forEach steps

Once created, these variables can be referenced in any subsequent step using the templating syntax.

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

🌐 Navigation Steps

Navigates to the given URL and waits for the page to load. By default, it only waits for the initial page load, not for any subsequent AJAX requests.

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

You can set waitForNetworkIdle to true to ensure the page is fully loaded before continuing.

{
  "action": "navigate",
  "url": "https://example.com/dashboard",
  "waitForNetworkIdle": true
}

Good to know:

  • Relative URLs are supported and will be resolved based on the current page
  • The navigate action will only wait for the initial page load, not for any subsequent AJAX requests

Wait for URL (waitForURL)

Waits for the current URL to match the given URL, optionally with a timeout. Supports wildcards.

{
  "action": "waitForURL",
  "url": "https://example.com/profile/**",
  "timeout": 3000
}

Wait for Element (waitForElement)

Waits for the given selector to appear on the page, optionally with a timeout.

{
  "action": "waitForElement",
  "selector": "#example",
  "timeout": 3000
}

Wait for Navigation (waitForNavigation)

Waits for the page navigation to happen. This step will not wait for the page to be fully loaded. Use the waitForNetworkIdle step for that purpose. Timeout is optional and defaults to 10 seconds.

{
  "action": "waitForNavigation",
  "timeout": 10000
}

Wait for Network Idle (waitForNetworkIdle)

Waits for the network to be idle. This is useful if you want to ensure the page has finished loading all resources. The step completes when there are no more network requests for 500ms. Timeout is optional and defaults to 15 seconds.

The navigate step has a waitForNetworkIdle option that can be set to true to get the same behavior.

{
  "action": "waitForNetworkIdle",
  "timeout": 10000
}

⚡️ Interaction Steps

Click Element (click)

Clicks the element specified by the given selector on the page.

{
  "action": "click",
  "selector": "#button"
}

Type Text (type)

Types the given text into the element specified by the given selector on the page.

{
  "action": "type",
  "selector": "#input",
  "value": "Hello World"
}

Select Dropdown (dropdownSelect)

Selects the given value from the dropdown specified by the given selector on the page. The selection happens based on the value attribute of the option.

{
  "action": "dropdownSelect",
  "selector": "#dropdown",
  "value": "Option 1"
}

Run JavaScript (runJs)

Runs the given JavaScript in the page context. If a promise is returned, it will be awaited.

If you want to use the result of a script in subsequent steps, use the extract step instead.

{
  "action": "runJs",
  "script": "document.querySelector('#example').click();"
}

✅ Verification Steps

These steps are used inside checkAuth to verify if the user is authenticated.

Check Element Exists (checkElementExists)

Checks if the given selector exists on the page. Typically used for authentication checks.

{
  "action": "checkElementExists",
  "selector": "#example"
}

Check URL (checkURL)

Checks if the current URL matches the given URL. Supports wildcard patterns like https://example.com/dashboard/**.

{
  "action": "checkURL",
  "url": "https://example.com"
}

Run JavaScript (runJs)

The runJs step can be used as verification step as well. By running a script that returns a truthy or falsy value, you can verify if the user is authenticated.

{
  "action": "runJs",
  "script": "document.cookie.includes('authToken');"
}

⚙️ Data Extraction Steps

These steps are used to load data from the page, like a list of items or a single value, and use it in subsequent steps.

Extract (extract)

Extracts a single piece of data from the page and stores it in a variable.

Using CSS fields:

{
  "action": "extract",
  "variable": "account",
  "fields": {
    "id": "#team-id",
    "name": "#team-name",
    "url": {
      "selector": "#team-link",
      "attribute": "href"
    }
  }
}

In this example account is used as variable name, and the fields id, name, and url are extracted using CSS selectors. They can be used in subsequent steps using the {{account.id}}, {{account.name}}, and {{account.url}} placeholders.

Using JavaScript:

{
  "action": "extract",
  "variable": "token",
  "script": "localStorage.getItem('authToken')"
}

This example creates a token variable that is extracted using JavaScript. The value can be accessed using the {{token}} placeholder. It's also possible to return an object.

Extract All (extractAll)

Extracts a list of data from the page, and runs the given steps for each item. This is commonly used to iterate over a list of invoices and download them.

For each element matching the selector, the fields are extracted and stored in the variable available in the forEach steps.

Good to know:

  • Each selector inside the fields object is automatically scoped to the matched element
  • The variable field is optional. If not provided, the extracted data will be stored in the default variable item
  • The current index can be accessed using the {{index}} placeholder. It starts at 0 and increments for each item

With CSS fields:

{
  "action": "extractAll",
  "selector": ".invoice-list .invoice-item",
  "variable": "invoice",
  "fields": {
    "id": "td.invoice-id",
    "date": "td.invoice-date",
    "total": "td.invoice-total",
    "url": {
      "selector": "a.invoice-link",
      "attribute": "href"
    }
  },
  "forEach": [
    {
      "action": "navigate",
      "url": "{{invoice.url}}"
    },
    {
      "action": "downloadPdf",
      "invoice": "{{invoice}}"
    }
  ]
}

With JavaScript:

When using JavaScript, the result should be an array of objects or values. If the result is a promise, it will be awaited.

{
  "action": "extractAll",
  "script": "Array.from(document.querySelectorAll('#year-selector option')).map(option => option.value);",
  "variable": "year",
  "forEach": [
    {
      "action": "dropdownSelect",
      "selector": "#year-selector",
      "value": "{{year}}"
    }
  ]
}

Extract Network Response (extractNetworkResponse)

Extracts data from a network response by matching the URL path. The URL parameter is used as a substring match against network requests, so you only need to provide a unique part of the URL path.

The response content is automatically parsed as JSON if possible, otherwise returned as a string. You can optionally transform the response using the transform parameter.

{
  "action": "extractNetworkResponse",
  "url": "api/invoices",
  "variable": "response"
}

With transformation:

{
  "action": "extractNetworkResponse",
  "url": "api/data",
  "variable": "items",
  "transform": "(response) => response.items.map(item => ({ id: item.id, date: item.createdAt, total: `${item.currency} ${item.amount}` }))"
}

The transformed data will be stored in the specified variable and can be used in subsequent steps.

📄 Document Retrieval Steps

These steps are used to download documents and process them in Invoice Radar. All steps require the document object to be passed as an argument, which contains the metadata of the document.

The document argument has the following fields:

Required:

  • id: The unique document ID (e.g., INV-123 or 123456)
  • date: The invoice date as string (e.g., 2022-01-01 or 01/01/2022 or January 1, 2022)

Recommended:

  • total: The invoice total amount including the currency (e.g., $100.00 or €100.00 or 100 EUR or 100,00€)
    • The built-in parser will try to extract the amount and currency from the string

Optional:

  • type: The type of the document (defaults to auto)
    • Can be set to auto, invoice, outgoing_invoice, receipt, refund or other
    • auto will try to detect the type based on the document
  • metadata: Additional metadata for the document (e.g., { "orderNumber": "12345" })

You can either pass every field separately or the whole object if it contains all required fields.

Download PDF (downloadPdf)

Downloads a PDF from the given URL.

{
  "action": "downloadPdf",
  "url": "https://example.com/invoice.pdf",
  "document": {
    "id": "{{item.invoiceId}}",
    "date": "{{item.date}}",
    "total": "{{item.total}}"
  }
}

Wait for PDF Download (waitForPdfDownload)

Waits for a PDF download. Timeout defaults to 15 seconds.

{
  "action": "waitForPdfDownload",
  "timeout": 10000,
  "document": {
    "id": "{{item.invoiceId}}",
    "date": "{{item.date}}",
    "total": "{{item.total}}"
  }
}

Prints the current page to a PDF file.

{
  "action": "printPdf",
  "document": {
    "id": "{{item.invoiceId}}",
    "date": "{{item.date}}",
    "total": "{{item.total}}"
  }
}

Download Base64 PDF (downloadBase64Pdf)

Downloads a PDF from a base64 encoded string.

{
  "action": "downloadBase64Pdf",
  "base64": "{{item.base64String}}",
  "document": {
    "id": "{{item.invoiceId}}",
    "date": "{{item.date}}",
    "total": "{{item.total}}"
  }
}

🔀 Conditional Logic Steps

If (if)

Runs the given steps if the condition is true. If the condition is false, the else steps are executed.

{
  "action": "if",
  "script": "'{{invoice.url}}'.includes('pdf')",
  "then": [
    {
      "action": "click",
      "selector": "#example"
    }
  ],
  "else": [
    {
      "action": "navigate",
      "url": "https://example.com/fallback"
    }
  ]
}

📦 Miscellaneous Steps

Sleep (sleep)

Waits for the given amount of time in milliseconds.

This is generally not recommended. In most cases, it's better to use the waitForElement, waitForURL or waitForNetworkIdle steps.

{
  "action": "sleep",
  "duration": 1000
}

Expose Option (exposeOption)

Exposes a configuration option to the user. The config field is the key of one of the options in the configSchema.

For example, if the configSchema is { "teamId": { "type": "string", "label": "Team ID" } }, the config field can be teamId.

{
  "action": "exposeOption",
  "config": "teamId",
  "option": "{{option}}"
}

✂️ Snippets

Snippets are pre-built sets of steps that simplify common tasks. The steps for a specific snippet are visible inside the developer tools.

Currently, it's not possible to create custom snippets. If you have a common task that you think would be useful as a snippet, please create an issue on GitHub.

Get Invoice from Stripe URL (getInvoiceFromStripeUrl)

Extracts an invoice from a Stripe invoice URL.

{
  "action": "runSnippet",
  "snippet": "getInvoiceFromStripeUrl",
  "args": {
    "url": "https://invoice.stripe.com/i/inv_123"
  }
}

Get Invoices from Stripe Customer Portal (getInvoicesFromStripeBillingPortal)

Extracts available invoices from a Stripe billing portal.

{
  "action": "runSnippet",
  "snippet": "getInvoicesFromStripeBillingPortal",
  "args": {
    "url": "https://stripe-portal.example.com/billing"
  }
}