Skip to Content

Invoice Pilot

Invoice Pilot extends WooCommerce with country-aware invoicing for the 27 EU member states. It captures the right billing fields at checkout (Italian SDI / PEC codes, French SIRET, German Leitweg-ID, Polish NIP, Romanian CUI, and so on), then issues immutable PDF and XML invoices, credit notes, proformas and quotes from the order. The PDF is rendered with mPDF; the XML envelope is picked automatically from the buyer’s country and covers eleven national profiles including FatturaPA (IT), XRechnung (DE), KSeF FA(2) (PL), Factur-X (FR), CIUS_RO (RO), Facturae (ES) and UBL 2.1 / PEPPOL BIS 3.0 as the generic fallback.

Beyond the document engine, Invoice Pilot ships first-class integrations with six accounting providers — SmartBill (Romania), Fatture in Cloud (Italy), Xero, QuickBooks Online, Fortnox (Sweden) and Sage — a VAT validator that consults the European VIES service with a per-country format fallback, a dashboard with KPI cards and trend charts, and an optional multi-provider AI layer (Anthropic Claude, OpenAI, Google Gemini, DeepSeek, Grok xAI) for checkout smart-fill, compliance pre-flight, line translation and natural-language document search. The plugin also supports WordPress Multisite with per-site tables and a network-wide overview page.

Highlights

  • WooCommerce-driven document lifecycle for invoices, credit notes, proformas and quotes, with reserved numbering series, a clean issue / regenerate / reissue / void / credit-note flow, and per-document-type styling (disclaimer banner on non-fiscal docs, “Valid until” labels on quotes, “Refund total” on credit notes, payment block hidden on quote and credit note).
  • EU-27 country-specific billing fields registered against both the legacy shortcode checkout and the WooCommerce 8.6+ block checkout (via the Additional Checkout Fields API).
  • PDF rendering through mPDF using one of three bundled templates (Minimal, Classic, Modern), with picker for accent colour, text colour, font family and seller logo.
  • Eleven XML writers, dispatched automatically from the buyer country: FatturaPA (IT), Factur-X / CII (FR), XRechnung 3.0 (DE), KSeF FA(2) (PL), CIUS_RO 1.0.0 (RO), Facturae 3.2.2 (ES), SAF-T PT (PT), OIOUBL (DK), Finvoice 3.0 (FI), ebInterface 6.1 (AT), myDATA InvoicesDoc (GR / EL), with UBL 2.1 / PEPPOL BIS 3.0 as the universal fallback.
  • VAT validation chain combining the European VIES SOAP service with offline per-country regex validation, a DB-backed cache and an hourly cron that revalidates stale entries.
  • Six accounting integrations — SmartBill, Fatture in Cloud, Xero, QuickBooks Online, Fortnox and Sage — each with encrypted credentials, push / status / void operations and a retry queue. The Integrations settings tab uses a sticky provider selector so the panel you were configuring stays open across saves.
  • Optional AI layer with five providers (Anthropic, OpenAI, Google Gemini, DeepSeek, Grok xAI) covering smart-fill, compliance check, line translation and natural-language search; the plugin works fully without an API key.
  • Dashboard with period selector, five KPI cards and two trend charts; a separate Integration Log records every push and failure.
  • WordPress Multisite support — each sub-site has its own tables, settings and numbering counters, with a network admin page that aggregates statistics.

Requirements

ComponentMinimum
WordPress5.8 (tested up to 7.0)
PHP8.0
WooCommerce7.0
DatabaseMySQL 5.7 or MariaDB 10.2 (the dashboard SQL uses JSON_EXTRACT / JSON_UNQUOTE against the immutable snapshot column)

The block-checkout integration is registered against the WooCommerce Additional Checkout Fields API (introduced in WooCommerce 8.6). On older WooCommerce versions the legacy woocommerce_billing_fields filter still adds VAT, tax-code and country-specific fields to the shortcode checkout, so the plugin degrades gracefully.

Installation

  1. Download the latest Invoice Pilot ZIP from the GitHub Releases  page.
  2. In WordPress, open Plugins → Add New → Upload Plugin.
  3. Choose the ZIP and click Install Now.
  4. Click Activate Plugin.
  5. Open Invoice Pilot → Settings to configure the seller, numbering series and optional integrations.

Activation creates the plugin’s database tables, installs the default settings and seeds five numbering series (one per document type): INV (invoice, default), REC (receipt), CN (credit note), PRO (proforma) and Q (quote), all using the YYYY-NNNN pattern with a yearly reset. Four cron jobs are also scheduled: daily log cleanup, fifteen-minute retry of failed integration pushes, hourly VIES revalidation and daily Fatture in Cloud token refresh.

On WordPress Multisite, the same per-site bootstrap runs automatically when a new sub-site is created (wp_initialize_site).

Configuration

All Invoice Pilot screens live under the top-level Invoice Pilot menu in the WordPress admin sidebar:

  • Dashboard — KPI cards and trend charts.
  • Documents — modern data-grid listing every issued document (invoice, credit note, proforma, quote, receipt) with a unified toolbar (AI search + type filter), colour-coded status pills (paid / void / converted / draft / issued), 20-row pagination and inline PDF / XML / Delete actions.
  • Settings — eight-tab configuration page (documented below).
  • Log — integration log entries with retention and a manual cleanup action.

The Settings page is split into the following tabs, in the order they appear in the UI:

  1. General
  2. Series
  3. Document types
  4. Templates
  5. VAT validation
  6. Integrations
  7. AI
  8. Advanced

General

Invoice Pilot — Settings, General tab
Settings → General — License key, seller identity and document defaults.

The General tab is split into three cards: License, Seller details and Document defaults.

License

FieldNotes
License KeyPaste the PILOT-XXXX-XXXX-XXXX-XXXX key from your order confirmation email and press Verify & Save to enable automatic plugin updates from the GitHub release feed. The plugin still issues documents without a key; only the auto-update channel is gated.

Seller details carries the identity printed on every issued document; Document defaults carries a small number of WooCommerce-level defaults.

FieldDefaultNotes
Seller nameemptyFree text.
VATemptySeller VAT identifier.
Tax codeemptyItalian codice fiscale or equivalent.
AddressemptyStreet.
ZIP / CAPemptyPostal code.
Cityempty
Province (2 letters, IT only)emptyForce-uppercased on save.
Country (ISO, 2 letters)ITISO-3166-1 alpha-2; force-uppercased.
EmailemptyValidated as an email address.
LogoemptyPicked from the WordPress Media Library. PNG or SVG with a transparent background works best; recommended height 64–128px. The logo is printed top-right on the invoice.
IBANemptyUsed by writers that emit payment instructions. Printed in the invoice footer and embedded in FatturaPA <DatiPagamento>.
Bank nameemptyFree text — printed under the IBAN in the invoice footer and emitted as <IstitutoFinanziario> inside the FatturaPA <DettaglioPagamento> block.
SWIFT / BICempty8 or 11 alphanumeric characters; uppercased and stripped of whitespace on save. Printed alongside the IBAN and emitted as <BIC> in FatturaPA.
Trigger statusprocessingWooCommerce order status that triggers automatic invoice issuance. Allowed values: processing, completed, on-hold, pending.
Default seriesINVSlug of the numbering series used for new invoices.
VAT number format on PDFPrefixed — VAT IT04032690614 (VIES style, recommended)How the seller VAT is printed on the rendered invoice and PDF preview. Choices: Prefixed (country code in front of the number, mirroring the VIES-style format), Bare (number only, as typed in Seller details → VAT). Defaults to Prefixed.
Country-specific billing fieldsItaly only (SDI / PEC / fiscal regime)Tri-state selector controlling which country-specific billing fields are exposed at checkout. Choices: Off — only universal VAT and tax-code shown, Italy only (SDI / PEC / fiscal regime), All EU-27 country-specific fields. Applies to both the block checkout and the legacy shortcode checkout. Every field carries a translatable label (e.g. SDI recipient code, Certified email (PEC), SIRET, Steuernummer) — the old raw snake_case names are gone.

Series

Invoice Pilot — Settings, Series tab
Settings → Series — CRUD table over numbering series with per-type pattern, counter and reset strategy.

The Series tab is a CRUD table over the numbering series stored in the plugin’s own series table. Each row controls how documents of a given type are numbered.

Columns: Slug, Pattern, Counter, Reset, Default, Enabled, Actions (Edit / Delete).

The Add / Edit form exposes:

FieldAllowed valuesDefault
SlugLowercase identifier. Must be unique.empty
Document typeinvoice, receipt, credit_note, proforma, quote.invoice
PatternFree text; placeholders {YYYY} (year) and {NNNN} (counter) are expanded at issue time.INV-{YYYY}-{NNNN}
CounterInteger, one or higher. Next number to assign — the very next document issued from this series will use this exact value (so Counter = 47 issues INV-2026-0047 next, not INV-2026-0048).1
Reset strategynever, yearly.never
DefaultBoolean — mark this series as the default for new documents of this type.off
EnabledBoolean — allow this series to be used.on

Renaming a slug updates the series row in place (preserving the integer id and any references) and migrates the default_series setting automatically if it pointed at the old slug. Deleting a series does not remove existing documents; they keep their numbers.

Document types

Invoice Pilot — Settings, Document types tab
Settings → Document types — optional document types and FatturaPA bollo/ritenuta defaults.

The Document types tab toggles optional document types and exposes the FatturaPA-specific bollo and ritenuta settings.

Document types card

ToggleDefaultDescription
Auto-issue credit note on WC refundonWhen a WooCommerce refund is created, automatically issue a credit note linked to the original invoice.
Enable proforma documentsonShow a “Create proforma” button on the WC order screen and allow conversion to invoice.
Enable quote (preventivo) documentsonShow a “Create quote” button on the WC order screen. Quotes are non-fiscal: a PDF is produced but no XML.

FatturaPA — Italian B2B card

FieldDefaultDescription
Bollo virtuale assoltooffEmit DatiBollo (2,00 EUR virtual stamp) on invoices above EUR 77,47 when the obligation has been declared to the Agenzia delle Entrate.
Apply Ritenuta d’accontooffCompute and emit DatiRitenuta on invoices to Italian B2B buyers.
Default rate20.00 %0–100, step 0.01.
Tipo ritenutaRT02RT01 (persone fisiche) or RT02 (persone giuridiche).
Causale pagamentoASingle uppercase letter from the SDI 1.1.5.2 table (e.g. A = professional services).

Templates

Invoice Pilot — Settings, Templates tab
Settings → Templates — radio picker for Minimal / Classic / Modern, colour and typography pickers, and a live PDF preview below (the preview iframe is captured separately, see below).

Pick one of three bundled PDF templates and customise its colours and typography.

TemplateDescription
MinimalClean sans-serif layout with a teal accent. Default.
ClassicSerif typography with a coloured header band. Traditional look for professional services.
ModernTwo-column header and rounded cards. Suited to design-led brands.

Additional fields:

FieldDefaultNotes
Primary colour#1e8a8aNative HTML5 colour picker; accent for headings, dividers and table headers.
FontSite theme font (system stack)One of: default, dejavusans, dejavuserif, dejavusansmono, helvetica, times, courier. The default value uses the site’s system font stack with DejaVuSans as the PDF fallback.
Text colour#222222Default body-text colour. Muted captions and footers keep their lighter tone.

The tab also embeds a live PDF preview (rendered against the /wp-json/invoice-pilot/v1/preview-template REST endpoint) so you can compare templates side-by-side before saving. Changing the radio swaps the iframe immediately; the choice persists only when you press Save template.

Invoice Pilot — live PDF preview (Modern template, invoice)
Live preview rendered through mPDF — Modern template, invoice document type, your real seller details (logo, primary colour, IBAN) and a sample buyer / line items.

A Document type selector sits above the iframe so you can preview how each of the four document types is rendered — invoice, credit_note, proforma, quote — with the same template, sample seller and sample buyer. The differences applied per type are:

TypeTitleNumber prefixStatus pillDisclaimer bannerPayment / IBAN
invoiceInvoiceINV-ISSUEDshown
credit_noteCredit noteCN-CREDIT NOTERefund of INV-…hidden
proformaProformaPRO-PROFORMAProforma — not a fiscal document.shown
quoteQuoteQ-QUOTEQuote — not a fiscal document, subject to acceptance.hidden

Quotes additionally relabel the prominent “Issued” / “Due date” cells to Valid until, and rename the hero total to Estimated total; credit notes rename it to Refund total. These differences come from a per-type label override map and a doc_type_context() helper fed into the template engine, so the three bundled designs (Minimal / Classic / Modern) keep a consistent visual identity across document types without duplicating template files.

The footer always carries the buyer country in its full English form (e.g. Germany, not DE) — the ISO code from the order is resolved through PHP’s Locale::getDisplayRegion() before render, which keeps the rendered invoice readable for human buyers and tax auditors. The seller VAT itself is printed according to VAT number format on PDF in General → Document defaults — defaulting to the VIES-style prefixed form (VAT IT04032690614), with a Bare option for jurisdictions that prefer the bare number.

The dispatcher that picks the right XML envelope per buyer country is the invoice_pilot_xml_writer_for_country filter, so host code can override per ISO (see Hooks and filters).

VAT validation

Invoice Pilot — Settings, VAT validation tab
Settings → VAT validation — validator chain (VIES + per-country format), cache TTL and state, reverse-charge toggles, a live validator tester and the EU-27 standard-rate seeder.

VAT identifiers entered at checkout (and on any address screen that exposes the field) are run through a chain of validators. Each validator is enabled by an independent toggle and runs in order until one returns a positive result; both successful and negative answers are cached for the configured TTL.

ValidatorDefaultDescription
VIES (EU SOAP)onCross-checks EU VAT IDs against the European Commission VIES service.
Per-country formatonOffline regex validation per country. Always recommended as a fallback.
FieldDefaultRange / Notes
Cache TTL (hours)241720. Failed VIES lookups older than 6 hours are revalidated by the hourly cron.
Intra-EU B2B reverse chargeonWhen the buyer is in a different EU member state from the seller and supplies a VAT number the chain confirms as valid, WooCommerce zeros the VAT on the cart automatically (the buyer self-accounts in their own country). The VAT input also gains a live green ✓ badge when the lookup succeeds and a red ✕ when it fails.
Deduct VAT if customer is located in base countryoffMost jurisdictions do NOT allow this — leave off unless you have specific tax advice that says it applies to your business. When on, a valid in-country B2B VAT triggers the reverse-charge deduction even on domestic sales.

A read-only Cache state row reports the number of cached entries and how many have expired and are pending eviction.

Test VAT validation — a small tester card below the settings card runs every provider directly against a single VAT, bypassing the chain order and the cache, so you can tell whether VIES actually confirmed the number or only the offline format check did.

Seed EU-27 standard VAT rates — the bottom card populates WooCommerce → Settings → Tax → Standard rates with the current standard VAT rate for every EU-27 member state (AT 20% BE 21% BG 20% HR 25% CY 19% CZ 21% DK 25% EE 22% FI 25.5% FR 20% DE 19% GR 24% HU 27% IE 23% IT 22% LV 21% LT 21% LU 17% MT 18% NL 21% PL 23% PT 23% RO 21% SK 23% SI 22% ES 21% SE 25%). By default only missing countries are inserted; tick Overwrite existing rates to force-refresh every row to the canonical value (useful after the EU bumps a national rate). The card also lists every (ISO, rate) pair so you can see exactly what will be written before pressing the button.

Integrations

The Integrations tab renders one panel per registered integration provider behind a single Provider selector at the top — pick the provider you want to configure and only its card is visible, the others stay in the DOM hidden. The selector is sticky across form saves: when you save a provider’s form (or land on the tab with ?integration=<id> in the URL), the next render keeps that provider selected, so you don’t get bounced back to whichever provider is enabled first in the registration order.

By default Invoice Pilot ships six providers; third-party code can register additional ones through the invoice_pilot_integration_providers filter.

Every provider panel is closed by a Connection Status card with a Test Connection button. The button issues a lightweight request against the saved credentials and prints the upstream response — save the form first if you have just pasted new tokens.

SmartBill

Invoice Pilot — Integrations, SmartBill panel
Integrations → SmartBill — enable toggle, API username, encrypted token, CIF and series.

Romanian invoicing provider. Credentials are encrypted at rest using the plugin’s symmetric crypto layer.

FieldDefaultNotes
Enable SmartBilloffPush issued invoices to SmartBill as soon as they are emitted.
API usernameemptyThe username you use to sign in to SmartBill.
TokenemptyPaste your SmartBill API token. The stored value is encrypted; leave the field blank on subsequent saves to keep it.
CIF (company)emptyRomanian company VAT code.
SeriesemptySmartBill series used for pushed invoices.

When enabled, Invoice Pilot calls POST /SBORO/api/v2/invoice on issuance, then pull_status to reconcile and void when an invoice is cancelled.

Fatture in Cloud

Invoice Pilot — Integrations, Fatture in Cloud panel
Integrations → Fatture in Cloud — OAuth tokens, company id and the Create customers toggle.

Italian invoicing provider. OAuth tokens are stored encrypted at rest. The daily invoice_pilot_refresh_fic_token cron refreshes the access token automatically when the integration is enabled.

FieldDefaultNotes
Enable Fatture in CloudoffPush issued documents (invoices, credit notes, proforma, quotes) to Fatture in Cloud as soon as they are emitted.
Client IDemptyOAuth client identifier.
Access tokenemptyPaste the OAuth access token. The stored value is encrypted; leave the field blank on subsequent saves to keep it.
Refresh tokenemptySame handling as the access token.
Company ID0Numeric company identifier in your Fatture in Cloud account.
Create customersonAutomatically create a customer record on FIC when a new buyer is invoiced.

Per the Fatture in Cloud product policy, Invoice Pilot does not submit FatturaPA to the SDI on your behalf. SDI submission is left to a separate manual step from inside your FIC account.

Xero

Invoice Pilot — Integrations, Xero panel
Integrations → Xero — top: one-click connection panel with the redirect URI to register on developer.xero.com. Bottom: app credentials and behaviour defaults. Below: a Connection Status section with a live Test Connection button.

Global accounting platform. OAuth 2.0 tokens are encrypted at rest. The settings tab is laid out as Connection (status + Connect / Disconnect buttons) on top and Settings (app credentials + push behaviour) below.

Connecting

Invoice Pilot ships with a built-in OAuth flow — you no longer have to do the dance in Postman and paste four strings into the form. The end-to-end setup is:

  1. Create a Web app on developer.xero.com  with the redirect URI printed in the Connection panel — copy it verbatim, Xero matches it character-by-character. Apps created after 2 March 2026 can only request the granular scope set; Invoice Pilot picks the right one automatically.
  2. Generate a Client secret on the Xero app page (Xero shows it only once), then paste Client ID and Client secret into the Settings form and save.
  3. Click Connect to Xero. You’ll be sent through the standard consent screen and, if your account authorises more than one organisation, you’ll be redirected to an in-card picker to choose the target tenant. Tokens are exchanged + persisted automatically.
  4. Disconnect clears the access + refresh tokens and the tenant id while keeping the app credentials around for an easy reconnect.

Pushes use POST /Invoices with the standard Idempotency-Key header derived from the local invoice id + number, so a network retry collapses to the same Xero InvoiceID instead of creating a duplicate. The refresh token rotates automatically on 401; if it ever expires (Xero invalidates refresh tokens after 60 days of inactivity) just hit Connect again.

Fields
FieldDefaultNotes
Enable XerooffPush issued documents to Xero as soon as they are emitted.
Client ID / Client secretemptyOAuth 2.0 app credentials from the Xero Developer Portal. Required before Connect can be used.
Access token / Refresh token (advanced)emptyAuto-populated by the Connect button. Only paste manually if you obtained tokens outside this UI.
Tenant IDemptyXero organisation UUID. Auto-populated by Connect (single org) or set via the in-card tenant picker (multiple orgs).
Default account code200Revenue account code stamped on every pushed line. Region defaults: UK/NZ 200, US 400, AU 200. Find yours under Accounting → Chart of accounts in Xero.
Default tax typeOUTPUTXero TaxType applied to taxed lines. Common values: OUTPUT (standard sales tax), OUTPUT2 (reduced rate), EXEMPTOUTPUT, NONE. Zero-VAT lines fall back to NONE automatically.
Invoice status on pushAUTHORISEDOne of DRAFT (editable in Xero, not yet a real invoice), SUBMITTED (awaiting approval), AUTHORISED (finalised). Anything else is sanitised back to AUTHORISED.
Payment account UUIDemptyXero bank/cash AccountID used when registering payments. Find it via GET /api.xro/2.0/Accounts?where=Type=="BANK" or the Xero UI (Chart of accounts → click the bank account → URL contains the UUID). Leave blank to disable payment recording.

QuickBooks Online

Invoice Pilot — Integrations, QuickBooks Online panel
Integrations → QuickBooks Online — top: one-click connection panel with the redirect URI to register on developer.intuit.com. Bottom: app credentials, environment switch and behaviour defaults. Below: a Connection Status section with a live Test Connection button.

Intuit QuickBooks Online — US / CA / UK / global. OAuth 2.0 tokens are encrypted at rest. The settings tab is laid out as Connection (status + Connect / Disconnect buttons) on top and Settings (app credentials + push behaviour) below.

Connecting

Invoice Pilot ships with a built-in OAuth flow — you no longer have to do the dance in Postman and paste five strings into the form. The end-to-end setup is:

  1. Create an app on developer.intuit.com  with QuickBooks Online and Payments as the platform and the com.intuit.quickbooks.accounting scope. Open the Keys & OAuth tab and switch between Development and Production depending on which environment you target — each has its own client_id + secret pair.
  2. Add the redirect URI printed in the Connection panel to the Redirect URIs list and click Save — Intuit accepts http://localhost for Development apps.
  3. Paste Client ID and Client secret into the Settings form, pick the matching Environment (Sandbox / Production) and save.
  4. Click Connect to QuickBooks. Intuit’s consent screen lets you pick the company you want the integration to write against; the chosen realmId is returned in the callback URL and saved automatically — there is no separate tenant picker.
  5. Disconnect clears the access + refresh tokens and the realm id while keeping the app credentials around for an easy reconnect.

Every push uses POST /v3/company/{realmId}/invoice with the requestid query parameter set to a stable per-invoice value — QBO collapses retried POSTs to the original response, so a network retry will never create a duplicate. Pushes also carry minorversion=75 so QBO returns current entity shapes (without it the API silently downgrades to its 2017-era contract). Refresh tokens last 100 days from issue and rotate on every use; the plugin handles the rotation transparently on 401.

Fields
FieldDefaultNotes
Enable QuickBooks OnlineoffPush issued documents as soon as they are emitted.
Environmentsandboxsandbox (default) hits sandbox-quickbooks.api.intuit.com; production hits quickbooks.api.intuit.com. Each environment has its own Client ID + secret on the Intuit app page.
Client ID / Client secretemptyOAuth 2.0 app credentials from the Keys & OAuth tab of your Intuit Developer app. Required before Connect can be used.
Access token / Refresh token (advanced)emptyAuto-populated by the Connect button. QBO access tokens last about 60 minutes and rotate via the refresh token; refresh tokens last 100 days from issue and rotate on every use. Only paste manually if you obtained tokens outside this UI.
Realm IDemptyQuickBooks company ID. Auto-populated by Connect — QBO passes it as realmId in the OAuth callback. Sandbox companies look like 9341457147734811; production realms are similar.
Default customer IDemptyQBO Customer.Id every pushed invoice is attached to. Required — QBO refuses invoices without a CustomerRef. Find it under Sales → Customers in the QBO UI or via GET /v3/company/{realmId}/query?query=select * from Customer.
Default item ID1QBO Item.Id used for every line. 1 is the default “Services” item in a fresh sandbox; find yours under Sales → Products and services.
Default tax codeNONQBO TaxCodeRef applied to each line. NON = non-taxable (default), TAX = default sales tax in US/CA accounts. Override per jurisdiction by setting up the tax code in QBO and pasting its name here.

Fortnox

Invoice Pilot — Integrations, Fortnox panel
Integrations → Fortnox — OAuth credentials, default customer number, default VAT and the Bookkeep on push toggle.

Swedish accounting platform. OAuth 2.0 credentials encrypted at rest.

FieldDefaultNotes
Enable FortnoxoffPush issued documents as soon as they are emitted.
Client ID / Client secretemptyOAuth 2.0 credentials from Fortnox developer portal.
Access token / Refresh tokenemptyEncrypted at rest.
Default customer numberemptyUsed when the buyer has no resolved Fortnox customer number.
Default VAT25Default Swedish VAT rate (in %) applied when no rate is mapped.
Bookkeep on pushoffAlso create the bookkeeping voucher when pushing the invoice.

Sage

Invoice Pilot — Integrations, Sage panel
Integrations → Sage Business Cloud — OAuth credentials, business id, default contact/ledger/tax-rate ids.

OAuth 2.0 accounting platform (Sage Accounting / Business Cloud).

FieldDefaultNotes
Enable SageoffPush issued documents as soon as they are emitted.
Client ID / Client secretemptyOAuth 2.0 credentials from Sage Developer.
Access token / Refresh tokenemptyEncrypted at rest.
Business IDemptyIdentifier of the Sage business the integration writes to.
Default contact id / ledger id / tax rate idemptyFallbacks applied when the snapshot does not carry the corresponding mapping.

AI

Invoice Pilot — Settings, AI tab
Settings → AI — provider picker (Anthropic / OpenAI / Google Gemini / DeepSeek / Grok), encrypted API key, Test Connection, and four feature toggles with per-hour rate limits.

The AI tab is split into two cards: Provider Configuration and Features. The plugin works fully without an API key; this tab adds optional AI-powered capabilities.

Provider Configuration

FieldNotes
ProviderAnthropic (default), OpenAI, Google Gemini, DeepSeek or Grok (xAI). Each provider keeps its own encrypted API key, so you can switch back and forth without re-pasting credentials.
API KeyStored encrypted. The card shows a green Configured badge when a key is already on file. The “Get your API key from …” link points to the chosen provider’s console.
ModelPer-provider list (see table below). The first model in the list is used as the default when no model is configured.
Test ConnectionCalls the provider’s messages / chat/completions endpoint with a one-token prompt and reports success or the upstream error.

Models offered per provider:

ProviderModels
AnthropicClaude Opus 4.7 (best quality, default), Claude Sonnet 4.6 (recommended), Claude Haiku 4.5 (fast, cheap)
OpenAIGPT-5 (best quality), GPT-5 mini (fast), GPT-4o, GPT-4o mini (cheapest)
Google GeminiGemini 2.5 Pro, Gemini 2.5 Flash (best value), Gemini 2.5 Flash Lite (cheapest)
DeepSeekDeepSeek V3.2 Chat, DeepSeek V3.2 Reasoner
Grok (xAI)Grok 4.1 Fast, Grok 4, Grok 3, Grok 3 Mini

Features

ToggleDefaultDescription
Smart-fill billingoffCustomers paste a free-form billing block at checkout; the model fills the structured form.
Smart-fill calls per hour5Per-session rate limit.
Compliance pre-flight checkoffHave the AI scan each invoice before issuance and flag potential issues.
Block issuance on error-level findingsoffWhen a critical issue is found, prevent the invoice from being issued.
Compliance calls per hour10
Translate line descriptionsoffUse AI to translate invoice lines into the buyer’s language. Polyglot-aware when the sibling plugin is installed.
Natural-language document searchoffFree-text queries on the Documents admin page.
Search calls per hour10

Advanced

Invoice Pilot — Settings, Advanced tab
Settings → Advanced — log retention, uninstall behaviour, manual maintenance actions and version footer.

Retention & uninstall

FieldDefaultRange
Log retention (days)9013650. Integration log entries older than this are purged by the daily cron.
Wipe data on uninstalloffDrop all Invoice Pilot tables and options when the plugin is uninstalled. Destructive. Off by default.

Maintenance actions

  • Run log cleanup now — fires the invoice_pilot_cleanup_logs action immediately instead of waiting for the daily cron.
  • Purge validation cache — deletes every row from the VAT validation cache table.

A small Versions row at the bottom prints the current plugin version and database schema version.

Usage

Auto-issuing an invoice from a WooCommerce order

The default workflow requires no manual action.

  1. A customer places an order on WooCommerce. The checkout exposes the VAT number and Tax code fields plus any country-specific fields registered for the billing country (for example SDI recipient code and Certified email (PEC) on IT orders). The VAT field validates live as the customer types — a green ✓ badge appears inside the input when the chain confirms the number, a red ✕ when it fails. When the buyer is in a different EU member state and the VAT validates, WooCommerce zeroes the VAT on the cart automatically (intra-EU B2B reverse charge — see Settings → VAT validation).
  2. When the order reaches the trigger status defined under Settings → General → Trigger status (processing by default), Invoice Pilot issues an invoice using the Default series (INV by default), persists an immutable JSON snapshot of the order, renders the PDF, generates the XML envelope for the buyer country, and pushes to any enabled integration.
  3. The order screen gains an Invoice Pilot meta box that lists the issued documents with links to the PDF and XML, plus action buttons for Regenerate, Reissue, Void, Create credit note, Create proforma, Create quote and Push to provider.
Invoice Pilot — WooCommerce order edit screen with the country-specific billing fields and the Invoice Pilot meta box
WooCommerce → Orders → Edit — the Billing card carries the country-specific fields registered for the buyer ISO (here Italian SDI recipient code, Certified email / PEC and Fiscal regime), and the Invoice Pilot meta box on the right shows the issued document number with PDF / XML links, a Regenerate document action and Other documents shortcuts for proforma and quote.

The Invoice Pilot meta box surfaces, for the latest non-void document on the order: the document number (e.g. INV-2026-0063), the status pill (Issued / Paid / Void), the PDF and XML download buttons (token-signed REST links), a Regenerate document action that re-renders the artefacts against the current template and seller settings without changing the document number, and an Other documents section that exposes one-click Create proforma and Create quote buttons. When an integration is enabled, a Push to provider button appears alongside the PDF / XML links and replays the integration call against the configured target.

Issuing manually

If automatic issuance is disabled or the order has not yet reached the trigger status, the order meta box exposes an Issue now button. The same flow applies — snapshot, PDF, XML, integration push — but it runs on demand.

Credit notes from refunds

When Auto-issue credit note on WC refund is on (the default), any WooCommerce refund created against an order with an existing invoice triggers a credit note in the CN series. The credit note links back to the parent invoice and references it in the XML. The rendered PDF carries a “Refund of INV-…” disclaimer banner at the top, a CREDIT NOTE status pill, Refund total in the hero cell, and hides the IBAN / payment-method footer (the original payment flow no longer applies). You can also issue a credit note manually — full or partial — from the Actions card on the invoice’s edit screen as long as the parent invoice is in issued status.

Proformas and quotes

When the corresponding toggles are on, the order screen also exposes Create proforma and Create quote buttons. Both produce non-fiscal documents — a PDF is rendered but no XML is generated for quotes. The rendered PDF carries a visual treatment specific to its type: a disclaimer banner at the top (“Proforma — not a fiscal document.” / “Quote — not a fiscal document, subject to acceptance.”), a “QUOTE” / “PROFORMA” status pill in place of “ISSUED”, and on quotes the prominent date label switches to Valid until and the hero total to Estimated total. Quotes hide the IBAN / payment-method block since there is no payment due yet.

A proforma can be converted to an invoice with the Convert action, which re-numbers the document under the configured invoice series.

Sending an invoice to the customer

The plugin registers a Send Invoice Pilot invoice to customer order action under WooCommerce’s standard order-actions dropdown, which emails the PDF to the buyer using WordPress’s wp_mail().

Downloading documents

PDFs and XML envelopes are served from a publicly addressable but token-signed REST endpoint:

GET /wp-json/invoice-pilot/v1/download/{id}/{format}?token=…

{format} is pdf or xml. The token is generated when the document is issued and printed into the order meta box and the Invoices list table.

Dashboard

Invoice Pilot — Dashboard
Dashboard — Activity overview card with period selector and five KPI cards, Trends card with two time-series charts below.

Invoice Pilot → Dashboard opens an Activity overview card on top of a Trends card. The Activity overview exposes a period bar with four windows — 7 days, 14 days, 30 days (default) and 90 days — and five KPI cards:

  • Invoices — total document count issued in the period.
  • Net revenue — sum of net totals in the shop currency, rendered with the locale’s currency symbol and two decimal places (e.g. €3,876.09 or 3.876,09 € depending on the admin’s locale).
  • VAT collected — sum of VAT totals from the immutable snapshot. Same locale-aware currency formatting as Net revenue. A separate schema migration backfills this value for invoices issued before schema version 1.3.1, where the column was not populated at write time.
  • Avg value — net revenue divided by invoice count, also currency-formatted.
  • B2B / B2C — split of B2B (buyer has a VAT number) vs B2C invoices in the same period.

Below the KPIs, the Trends card renders two charts side-by-side — Invoices over time (a dual-axis line + area chart with the invoice count on the left axis and the net revenue trend filled on the right axis) and By buyer country (a donut chart of the top buyer ISO codes, with the colour legend below). All figures are hydrated from /wp-json/invoice-pilot/v1/dashboard?days=N.

Documents list

Invoice Pilot — Documents list
Documents — unified toolbar (AI search + type filter + running count) and the data grid with NUMBER, TYPE, STATUS, ORDER, ISSUED, TOTAL, COMPLIANCE, FILES and ACTIONS columns.

Invoice Pilot → Documents lists every issued document with status pills (paid / void / converted / draft / issued — colour-coded by lifecycle state), a Compliance column carrying the colour-coded badge produced by the AI pre-flight check, and inline PDF / XML / Delete actions per row. The page paginates 20 rows at a time and exposes a unified toolbar that combines the AI free-text search with a document-type filter (invoice / credit_note / proforma / quote / receipt) plus a running count on the right. When AI search is enabled, the search box accepts free-text queries (for example, “German invoices last month over 1,000 EUR”) that the configured provider translates into a list query; the resolved filter chips appear above the table so you can see exactly how the model parsed your phrase.

WooCommerce Orders list

Invoice Pilot — Invoice number column on the WC Orders screen
WooCommerce → Orders — an Invoice column lists the document number assigned to each order, with a small preview icon that links to the rendered PDF.

Invoice Pilot adds a single Invoice column to the standard WooCommerce Orders list (/wp-admin/admin.php?page=wc-orders) so the shop owner can see at a glance which orders have already been documented and which haven’t, without leaving the Orders screen. The column sits between Order and Date and shows the document number assigned by the configured series (for example INV-2026-0063) read verbatim from the immutable number column, with a small eye preview icon next to the number that opens the rendered PDF inline in a new tab.

Orders without an issued document render an em-dash — useful when debugging trigger-status mismatches or filtering for orders that need a manual wp invoice-pilot issue run. The same renderer wires both the legacy posts-table column (manage_edit-shop_order_columns) and the HPOS column (manage_woocommerce_page_wc-orders_columns), so the experience is identical regardless of which orders storage your shop is on.

Integration log

Invoice Pilot — Integration log
Log — chronological integration push log with provider/action filters and a per-row Delete action; payload fields are redacted on write by Core\Logger.

Invoice Pilot → Log records every integration push, response and failure. The toolbar at the top combines a Bulk actions selector + Apply button (currently a one-action bulk-delete), a provider dropdown and an action dropdown — both populated from the values actually seen in the log so they only ever show filters that match a real row — and a running entries count on the right.

The data grid carries eight columns:

ColumnNotes
DATE (UTC)Timestamp pill, UTC. Sorted descending by default.
PROVIDERLower-cased provider slug (fattureincloud, smartbill, xero, …).
ACTIONOperation that produced the entry (push, pull_status, refresh_token, void).
INVOICE#<id> link back to the document, or an em-dash for entries unrelated to a single invoice (token refreshes, manual maintenance).
HTTPColoured pill carrying the upstream status code — green for 2xx, amber for 4xx, red for 5xx (or any entry with a non-null error column).
ERRORUpstream error message in red text when the call failed; em-dash on success.
MSWall-clock duration of the call in milliseconds.
ACTIONSA red Delete action per row for one-off cleanup.

Sensitive payload fields are redacted on write by the plugin’s Core\Logger, so request and response bodies are safe to keep in the log. Old entries are pruned by the daily invoice_pilot_cleanup_logs cron according to the Log retention (days) setting in the Advanced tab.

Network admin (Multisite)

On a Multisite network, an additional Invoice Pilot Network page appears in the network admin sidebar. It aggregates invoice counts and totals across every sub-site that has Invoice Pilot active.

EU-27 invoicing

Invoice Pilot ships a registry of country-specific billing fields for every EU-27 member state. Each field is optional at checkout (the plugin does not force B2B-only data on a B2C order); validation fires only when the buyer country matches the field’s ISO.

The registry currently covers:

CountryFields
IT Italyei_recipient_code (7 alphanumeric, default 0000000), ei_certified_email (PEC), fiscal_regime (RF01–RF19)
FR Francesiren (9 digits), siret (14 digits), chorus_pro_service_code
DE Germanysteuernummer, ust_id, leitweg_id, hrb
ES Spainnif, face_oficina_contable, face_organo_gestor, face_unidad_tramitadora
PT Portugalnif (9 digits), atcud
NL Netherlandskvk_number (8 digits), btw_id
BE Belgiumbce_number (10 digits)
LU Luxembourg
AT Austriauid_nummer, firmenbuchnummer, steuernummer
IE Ireland
DK Denmarkcvr_number (8 digits), ean_location_number
SE Swedenorganisationsnummer
FI Finlandy_tunnus, ovt_code
PL Polandnip (10 digits), regon, ksef_id
CZ Czech Republicdic, ico (8 digits), data_box_id
SK Slovakiadic, ico (8 digits), data_box_id
HU Hungarytax_number, group_member_id
SI Sloveniavat_id, maticna_stevilka
HR Croatiaoib (11 digits)
RO Romaniacui
BG Bulgariaeik (9–13 digits), vat_id
GR Greeceafm (9 digits), dou_code
CY Cyprustic
MT Maltaid_number
LT Lithuaniacompany_code
LV Latviaregistration_number
EE Estoniaregistry_code

The block-checkout integration registers fields under the invoice-pilot/... namespace through the Additional Checkout Fields API. By default only the Italian fields are exposed in the block checkout to avoid overwhelming non-Italian shoppers; the All EU-27 fields at checkout toggle in General turns on the full set. The legacy shortcode checkout always renders the complete registry filtered by the selected billing country.

Country fields are persisted on the order, copied into the immutable invoice snapshot, and consumed by the XML writers — for example the Italian ei_recipient_code becomes CodiceDestinatario / PECDestinatario in the FatturaPA envelope, while the German leitweg_id becomes BuyerReference / EndpointID 0204 in XRechnung.

Integrations

SmartBill

SmartBill (Romania) is wired into the plugin’s IntegrationManager through the invoice_pilot_integration_providers filter and exposes the standard provider interface: push, pull_status, void and test_connection.

  • Push maps the invoice snapshot to the SmartBill JSON schema and calls POST /SBORO/api/v2/invoice with the configured CIF and series.
  • Status sync reconciles draft / issued / paid state when the fifteen-minute retry cron runs.
  • Void cancels a previously pushed invoice on SmartBill when the source invoice is voided in WordPress.

All actions are logged to the Integration log. Failures are queued and retried by the invoice_pilot_retry_integrations cron.

Fatture in Cloud

Fatture in Cloud (Italy) follows the same provider interface and maps the invoice snapshot to the entity / items_list shape expected by FIC’s issued-document endpoint. Italian country-specific fields are mapped explicitly:

  • ei_recipient_codeei_code
  • ei_certified_emailcertified_email
  • buyer VAT / tax-code / province / country → corresponding entity keys

OAuth credentials are encrypted at rest. The daily invoice_pilot_refresh_fic_token cron refreshes the access token when the integration is enabled. Setting Create customers to on causes the integration to create a new customer record in FIC on the first invoice for a buyer.

Invoice Pilot does not submit FatturaPA to the SDI on your behalf. SDI submission is left to a separate manual step from inside your Fatture in Cloud account.

AI smart-fill

The AI layer is fully optional. Without a configured API key the plugin still issues invoices, renders PDFs and XML, validates VAT, and pushes to integrations — only the four AI features below are unavailable.

Five providers are supported:

ProviderDefault modelAPI key URL
Anthropicclaude-opus-4-7console.anthropic.com 
OpenAIgpt-5platform.openai.com 
Google Geminigemini-2.5-proaistudio.google.com 
DeepSeekdeepseek-chatplatform.deepseek.com 
Grok (xAI)grok-4-1-fast-non-reasoningconsole.x.ai 

The API key is stored encrypted at rest using the plugin’s symmetric crypto layer. Pressing Test Connection issues a minimal request to the chosen endpoint and surfaces the upstream error if the credentials are wrong.

Four features can be toggled independently once a key is on file:

  • Smart-fill at checkout — a “Paste billing details” textarea appears at checkout. The model parses the free-form text and fills the structured WooCommerce billing form, including the country-specific fields. Rate-limited per session.
  • Compliance pre-flight check — every invoice is run through the model just before issuance, with the option to block issuance on error-level findings when a critical issue is detected (for example, an Italian B2B invoice missing the SDI recipient code).
  • Line auto-translate — invoice line descriptions are translated into the buyer’s language. When the sibling Polyglot  plugin is installed, the translation pipeline is delegated to it.
  • Natural-language document search — the search box on the Documents admin page accepts free-text queries that the model translates into a list query.

Each feature has its own per-hour rate limit.

Hooks and filters

Centralised hook names live in the \InvoicePilot\Core\Hooks class. The full list:

HookTypePurpose
invoice_pilot_redact_keysfilterExtra keys to redact from logged payloads.
invoice_pilot_xml_writer_for_countryfilterOverride the XML writer per buyer ISO. Two arguments: current writer, ISO.
invoice_pilot_validator_chainfilterOverride or extend the VAT validator chain.
invoice_pilot_integration_providersfilterRegister additional integration providers.
invoice_pilot_country_fieldsfilterAdd or remove country-specific checkout fields. Two arguments: current fields array, ISO code.
invoice_pilot_bootedactionFires after the plugin has booted. Passes the singleton.
invoice_pilot_register_modulesactionModule registration hook.
invoice_pilot_invoice_issuedactionFires after a new invoice is issued.
invoice_pilot_invoice_renderedactionFires after the PDF or XML is rendered.
invoice_pilot_integration_pushedactionFires after a successful integration push.
invoice_pilot_integration_failedactionFires after a failed integration push.
invoice_pilot_cleanup_logsactionDaily cron — purges old integration log entries.
invoice_pilot_retry_integrationsactionFifteen-minute cron — retries failed pushes.
invoice_pilot_revalidate_viesactionHourly cron — revalidates stale VIES cache entries.
invoice_pilot_render_integration_tabactionFired from the Integrations settings tab so providers can render their own settings cards.
invoice_pilot_refresh_fic_tokenactionDaily cron — refreshes the Fatture in Cloud access token.

Registering a custom XML writer:

add_filter( 'invoice_pilot_xml_writer_for_country', function ( $writer, $iso ) { if ( 'NL' === $iso ) { return new My_Custom_Nl_Writer(); } return $writer; }, 20, 2 );

Registering a custom integration provider:

add_filter( 'invoice_pilot_integration_providers', function ( array $providers ) { $providers[] = new My_Custom_Provider(); return $providers; } );

Hiding or extending country-specific checkout fields (for example to drop Italy’s ei_certified_email (PEC) and fiscal_regime (RF code) prompts when your shop never needs them — no plugin fork required):

add_filter( 'invoice_pilot_country_fields', function ( array $fields, string $iso ) { if ( 'IT' === $iso ) { $fields = array_values( array_filter( $fields, fn ( $f ) => ! in_array( $f->name, [ 'ei_certified_email', 'fiscal_regime' ], true ) ) ); } return $fields; }, 10, 2 );

The filter runs on both the PHP submit-validation path and the JS snapshot served to the WC Blocks checkout, so the two layers stay in sync. Field machine-names currently shipped (use these in the filter):

CountryField names
ITei_certified_email, fiscal_regime
FRsiren, siret, chorus_pro_service_code
DEsteuernummer, ust_id, leitweg_id, hrb
ESnif, face_oficina_contable, face_organo_gestor, face_unidad_tramitadora
PTnif, atcud
NLkvk_number, btw_id

The full per-country registry is defined in CountryFieldRegistry::install_defaults() and covers all EU-27 ISOs.

FAQ

Does Invoice Pilot submit FatturaPA to the SDI?

No. Invoice Pilot generates the FatturaPA XML and stores it on the order; SDI submission is intentionally left to a separate manual step (or to the Fatture in Cloud integration on your account).

Can I add a writer for a country that isn’t built in?

Yes. Hook into invoice_pilot_xml_writer_for_country and return your own implementation of \InvoicePilot\Modules\Xml\XmlWriterInterface.

Does it work on the WooCommerce block checkout?

Yes. Country-specific fields are registered through the WooCommerce 8.6+ Additional Checkout Fields API, so they appear in both the block checkout and the legacy shortcode checkout. On WooCommerce versions older than 8.6, only the legacy filter path is used.

Does it work on WordPress Multisite?

Yes. Each sub-site has its own tables, settings and numbering counters. A network admin page under Network Admin → Invoice Pilot Network aggregates invoice counts across the network. On new sub-sites, tables and default series are created automatically through the wp_initialize_site hook.

Are credentials encrypted?

Yes. SmartBill tokens, Fatture in Cloud OAuth tokens and the AI API key are encrypted at rest via \InvoicePilot\Core\Crypto. Leaving a token field blank on the next save keeps the existing stored value.

What happens to my data if I delete the plugin?

Nothing, unless you opt in. The default for Advanced → Wipe data on uninstall is off, so tables, options, integration logs and the validation cache are preserved across deactivation / reactivation. Toggle the option on if you want the uninstall.php routine to drop everything when WordPress deletes the plugin.

Where can I get an API key for the AI features?

Each provider has its own console: Anthropic at console.anthropic.com , OpenAI at platform.openai.com , Google AI Studio at aistudio.google.com , DeepSeek at platform.deepseek.com , and Grok at console.x.ai . The AI tab links directly to the chosen provider’s console.

Do I need an AI key for the plugin to work?

No. The AI features (smart-fill, compliance check, line translation, natural-language search) are optional. The core invoicing engine — document lifecycle, PDF and XML generation, VAT validation, integrations, dashboard — runs without an API key.

Troubleshooting

The invoice isn’t issued when the order moves to Processing

Check Settings → General → Trigger status. The default is processing; if you have customised it (for example to completed), the auto-issue routine only fires on the configured status. You can also press Issue now from the order meta box to issue manually regardless of the trigger.

The checkout shows too many (or too few) country fields

The default exposes only the Italian SDI fields. Open Settings → General → Document defaults → Country-specific billing fields and pick the scope you want:

  • Off — only universal VAT and tax-code fields are shown.
  • Italy only (SDI / PEC / fiscal regime) — default.
  • All EU-27 country-specific fields — every ISO in the registry.

The setting applies to BOTH the block checkout and the legacy shortcode checkout. Country-specific fields are still hidden client-side when the billing country does not match.

VAT validation hangs or times out

The VIES service is occasionally slow or unavailable. The plugin keeps a per-VAT cache for the configured TTL (24 hours by default) and revalidates stale entries hourly through the invoice_pilot_revalidate_vies cron. If VIES is offline, the Per-country format validator still accepts well-formed numbers. You can also raise the cache TTL under Settings → VAT validation.

The dashboard shows no data

The dashboard SQL relies on JSON_EXTRACT / JSON_UNQUOTE against the immutable invoice snapshot column. Make sure your database server is MySQL 5.7+ or MariaDB 10.2+. If the period bar shows the right window but the cards remain on --, open /wp-json/invoice-pilot/v1/dashboard?days=30 directly and check the response — REST authentication failures appear as rest_forbidden.

Integration push fails

Open Invoice Pilot → Log and locate the failed entry — the HTTP column flags non-2xx responses with a coloured badge and the Error column shows the upstream error message in red. The failed entry is automatically retried by the invoice_pilot_retry_integrations cron every fifteen minutes; you can also press Push to provider in the order meta box to retry immediately. Use the Delete action on a row to clear a one-off entry without waiting for the retention cron.

Test Connection on the AI tab reports an error

The message returned in red comes straight from the provider’s endpoint. Common causes:

  • An invalid or revoked API key — generate a new one and paste it into the API Key field, then save.
  • A model name that the account does not have access to — pick a different model in the dropdown.
  • Network egress blocked by the host — confirm outbound HTTPS to api.anthropic.com, api.openai.com, generativelanguage.googleapis.com, api.deepseek.com or api.x.ai is allowed.

Email alerts to the customer are not arriving

Customer invoice emails are sent through WordPress’s wp_mail() function. If no email arrives, the issue is almost always with the site’s mail configuration rather than with Invoice Pilot. Install a transactional mail plugin (for example, one that routes WordPress mail through SMTP) and trigger the Send Invoice Pilot invoice to customer order action again from a test order.

Last updated on