Skip to main content
Glama
getpopapi
by getpopapi
README.md
<!-- mcp-name: io.github.popapidev/pop-mcp -->

# pop-mcp

MCP (Model Context Protocol) server for **POP** — enabling LLMs to generate, submit, and manage Italian e-invoices (FatturaPA/SdI), Peppol, KSeF, ZUGFeRD/Factur-X, and PDF invoices directly from AI assistants.

> **npm:** `@getpopapi/pop-mcp` · **Remote:** `https://mcp.popapi.io/mcp`

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Node.js](https://img.shields.io/badge/Node.js-%3E%3D20-green)](https://nodejs.org/)

---

## Remote MCP (HTTP) — fastest way to get started

Don't want to install anything? `pop-mcp` runs as a hosted, multi-tenant MCP server at:

```
https://mcp.popapi.io/mcp
```

Head to [popapi.io](https://popapi.io) to grab a license key, then point any MCP-speaking client at
that URL with your key as a Bearer token. No local install, no `POP_API_KEY` env var, no build step
— this is the recommended way to try `pop-mcp` for most people. Use the local stdio setup below only
if you specifically need a Claude Desktop config running a process on your own machine.

### How it works

This endpoint speaks MCP **2026-07-28**, which is fully stateless: there is no `initialize`
handshake and no session to open or track. Every request is self-contained — it names its own
protocol version and capabilities — and the server answers it independently. Because of that,
this is a **multi-tenant** endpoint: it never reads a fixed `POP_API_KEY` from its own environment.
Every request must carry your own POP license key as a Bearer token:

```
Authorization: Bearer <your_license_key>
```

A missing or malformed `Authorization` header returns a `401` with `error_code: "unauthorized_user"`
before any POP API call is made. An invalid-but-well-formed key is passed straight through to POP's
API and surfaces whatever error POP returns (`unauthorized_user`, `insufficient_level`, etc.) — the
server does not re-validate keys itself.

Any modern MCP HTTP client can connect: Claude (remote connector), the OpenAI Responses API, n8n,
[MCP Inspector](https://github.com/modelcontextprotocol/inspector), or a custom integration — not
just Claude Desktop. All invoice, status, advanced, and onboarding tools are available; onboarding
tools use their own `onboarding_token` per call and don't require the Bearer key.

### Example with curl

Discover the server's supported protocol versions and capabilities (optional — clients can also
just call `tools/list` or `tools/call` directly and handle a version-negotiation error inline):

```bash
curl -X POST https://mcp.popapi.io/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_license_key_here" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: server/discover" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "server/discover",
    "params": { "_meta": { "io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientCapabilities": {} } }
  }'
```

List the available tools — every request is self-contained, so `_meta` (protocol version + client
capabilities) travels on every call, not just the first one:

```bash
curl -X POST https://mcp.popapi.io/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_license_key_here" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/list",
    "params": { "_meta": { "io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientCapabilities": {} } }
  }'
```

The tool catalog is identical for every license key, so `tools/list` and `server/discover`
responses carry a one-hour public cache hint (`ttlMs: 3600000, cacheScope: "public"`) — clients and
gateways may cache them across tenants.

> **`MCP-Protocol-Version` and `Mcp-Method` are required on every request** (per SEP-2243), and must
> match the body's `_meta.protocolVersion` and `method` exactly, or the server rejects the request
> with a `400` and JSON-RPC error `-32020` (`HeaderMismatch`). `tools/call` requests additionally
> require an `Mcp-Name` header matching `params.name`.

### Example with MCP Inspector

```bash
npx @modelcontextprotocol/inspector
```

Configure it to connect to `https://mcp.popapi.io/mcp` with header
`Authorization: Bearer <your_license_key>`.

This endpoint runs as a Vercel serverless function (`api/mcp.ts` → `src/mcpHandler.ts`). To run it
locally: `npx vercel dev` (requires `vercel link` to the project first).

---

## What is POP?

[POP](https://popapi.io) is a cloud service for electronic invoice generation and delivery, supporting:

- 🇮🇹 **Italian e-invoicing (FatturaPA/SdI)** — compliant with D.Lgs. 127/2015
- 🇪🇺 **Peppol** — pan-European cross-border B2B invoicing (UBL 2.1)
- 📄 **PDF invoices** — branded, with email delivery
- ✅ **Validation** — fiscal codes, VAT numbers, document pre-submission checks
- 🗄️ **Preservation** — Italian legal archival (conservazione sostitutiva)

---

## Tools Available (11 total)

### Invoice Creation
| Tool | Endpoint | Plan |
|------|----------|------|
| `pop_create_sdi_invoice` | POST `/create-xml` | Any |
| `pop_create_peppol_invoice` | POST `/create-ubl` | Any (Basic+ to submit) |
| `pop_create_pdf_invoice` | POST `/create-pdf` | Any (Basic+ for email) |
| `pop_create_ksef_invoice` | POST `/create-ksef-xml` | Any (KSeF setup for provider submission) |
| `pop_create_zugferd_invoice` | POST `/create-zugferd` | Any |
| `pop_sync_zoho_document` | POST `/integration/zoho/sync` | Zoho connector required |

### Status & Retrieval
| Tool | Endpoint | Plan |
|------|----------|------|
| `pop_get_invoice_status` | POST `/sdi/document-notifications` | Any |
| `pop_get_peppol_document` | POST `/peppol/document-get` | Basic+ |
| `pop_get_sdi_document` | POST `/sdi/document-get` | Basic+ |

### Validation & Advanced SdI
| Tool | Endpoint | Plan |
|------|----------|------|
| `pop_verify_sdi_document` | POST `/sdi/document-verify` | Basic+ |
| `pop_preserve_document` | POST `/sdi/document-preserve` | Basic+ |

---

## Prerequisites

- Node.js >= 20
- A [POP](https://popapi.io) license key
- For SdI/Peppol submission: active integration on your POP account (Basic/Growth plan)

---

## Authentication

### Get Your License Key

> **New to POP?** Visit [popapi.io](https://popapi.io) to create your account and get your license key.

API-only users can activate their account and obtain a `license_key` with this flow:

1. Open [https://popapi.io/otp-login/](https://popapi.io/otp-login/)
2. Enter your email address
3. Receive a one-time password (OTP) by email and enter it
4. Complete the configuration wizard
5. Open [https://popapi.io/](https://popapi.io/) → **Account > API**
6. Copy the default generated `license_key`

### Key Management

- Your account includes one default `license_key`, visible under **Account > API**
- You can generate additional keys linked to the same account from that same page
- Every `license_key` must be treated as a secret credential — do not commit it to source control

### Recommended First Steps

1. Get your `license_key`
2. Test it with `GET /account-profile`
3. Send one document-generation request with a real payload
4. Add optional delivery integrations only after local generation works

---

## Installation

### From npm (recommended)

```bash
npm install -g @getpopapi/pop-mcp
```

### From Source

```bash
git clone https://github.com/getpopapi/pop-mcp
cd pop-mcp
npm install
npm run build
```

---

## Configuration

Set your POP license key as an environment variable:

```bash
export POP_API_KEY=your_license_key_here
```

Optional — use the staging environment:

```bash
export POP_ENVIRONMENT=staging
```

---

## Claude Desktop Setup

Add to your `claude_desktop_config.json`:

**If installed from npm:**

```json
{
  "mcpServers": {
    "pop": {
      "command": "pop-mcp",
      "env": {
        "POP_API_KEY": "your_license_key_here"
      }
    }
  }
}
```

**If running from source:**

```json
{
  "mcpServers": {
    "pop": {
      "command": "node",
      "args": ["/path/to/pop-mcp/dist/cli.js"],
      "env": {
        "POP_API_KEY": "your_license_key_here"
      }
    }
  }
}
```

**Config file locations:**
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`

---

## Tool Reference

The `license_key` is always injected automatically from `POP_API_KEY` — never pass it manually.

### `pop_create_sdi_invoice`

Generate an Italian FatturaPA XML document. Optionally submit it to the SdI (Sistema di Interscambio).

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `data` | object | ✅ | Full invoice data (see Invoice Data Structure) |
| `submit_to_sdi` | boolean | — | Set `true` to submit to SdI. Requires Basic+ plan with active SdI integration. Default: `false` |
| `integration` | object | — | Override integration config. Overrides `submit_to_sdi` if set. |
| `environment` | string | — | Target environment (e.g. `"sandbox"`) |

**Integration options for `integration.use`:**
- `"sdi-via-pop"` or `"sdi"` — Submit via POP SdI
- `"pop-to-webhook"` — Deliver to a webhook (requires `id`)
- `"fatture-in-cloud"` — Deliver to Fatture in Cloud

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "user_agent": "pop-mcp",
  "user_agent_version": "1.0.0",
  "data": { "...invoice fields..." },
  "integration": { "use": "sdi-via-pop", "action": "create" }
}
```

> `integration` is omitted when `submit_to_sdi` is `false` and no override is provided (XML-only generation).

---

### `pop_create_peppol_invoice`

Generate a Peppol UBL 2.1 document. Optionally submit it to the Peppol network.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `data` | object | ✅ | Full invoice data. `customer_type` must be `"company"` or `"freelance"` |
| `submit_to_peppol` | boolean | — | Set `true` to submit to the Peppol network. Requires Basic+ plan. Default: `false` |
| `integration` | object | — | Override integration config |
| `environment` | string | — | Target environment |

**Integration options for `integration.use`:**
- `"peppol-via-pop"` or `"peppol"` — Submit via POP Peppol
- `"pop-to-webhook"` — Deliver to a webhook (requires `id`)

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "user_agent": "pop-mcp",
  "user_agent_version": "1.0.0",
  "data": { "...invoice fields..." },
  "integration": { "use": "peppol-via-pop", "action": "create" }
}
```

---

### `pop_create_pdf_invoice`

Generate a branded PDF invoice. Optionally email it to up to 3 recipients.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `data` | object | ✅ | Invoice data. Must include `data.pdf` for PDF-specific settings |
| `send_email` | boolean | — | Set `true` to email the PDF (requires `data.pdf.email_invoice`, Basic+ plan). Default: `false` |
| `environment` | string | — | Target environment |

**`data.pdf` fields:**

| Field | Description |
|-------|-------------|
| `doc_type_title` | Title shown on document (e.g. `"Invoice"`, `"Receipt"`) |
| `logo_url` | Company logo URL (HTTPS) |
| `head.store_info_address` | Supplier address string in header |
| `head.billing[]` | Customer billing address array |
| `head.shipping[]` | Shipping address array (optional) |
| `email_invoice.to` | Up to 3 recipient email addresses |
| `email_invoice.from` | Reply-to address |
| `footer_text` | Custom footer message |
| `total_tax` | Total tax amount as string |

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "user_agent": "pop-mcp",
  "user_agent_version": "1.0.0",
  "data": {
    "...invoice fields...",
    "pdf": {
      "doc_type_title": "Invoice",
      "logo_url": "https://example.com/logo.png",
      "head": { "store_info_address": "Via Roma 1, 00100 Roma IT", "billing": [] },
      "total_tax": "22.00",
      "email_invoice": { "to": ["customer@example.com"] }
    }
  }
}
```

---

### `pop_create_ksef_invoice`

Generate a Polish KSeF FA(3) XML invoice or credit note. Optionally submit it through a configured KSeF provider integration.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `data` | object | ✅ | Full invoice data for KSeF FA(3) generation |
| `integration` | object | — | Optional KSeF provider submission config: `{ use: "ksef" \| "ksef-via-pop", action }` |
| `environment` | string | — | Target environment (e.g. `"sandbox"`) |

**Domain rules specific to KSeF:**
- Poland only — `transfer_lender.personal_data.tax_id_vat.country_id` must be `"PL"` with a 10-digit NIP as `id_code`
- `customer_type` must be `"company"` or `"freelance"` (no private individuals)
- `nature` is **always required** at the top level for KSeF (unlike SdI/Peppol, where it's only required at 0% VAT) — reuses the same SdI nature codes (`N1`, `N2.1`, `N2.2`, `N3.1`, `N3.2`, `N4`, ...) to derive KSeF's internal fiscal variant
- `transmitter_data` is not used (SdI-only concept)
- `payment_data.payment_details` only accepts `MP01`, `MP02`/`MP03`, `MP05`, `MP08` — other payment method codes are rejected at generation time
- Base XML generation is available on any plan; provider submission via `integration.use: "ksef"` requires a Basic+ plan and the supplier already enrolled as a KSeF legal entity in the POP dashboard

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "user_agent": "pop-mcp",
  "user_agent_version": "1.0.0",
  "data": { "...invoice fields...", "nature": "N1" },
  "integration": { "use": "ksef", "action": "create" }
}
```

> `integration` is omitted entirely for local XML-only generation (no provider submission).

**Returns:** raw FA(3) XML (`application/xml`) for local generation, or JSON (with a UUID) when submitted through a provider integration.

---

### `pop_create_zugferd_invoice`

Generate a ZUGFeRD/Factur-X document package: a visual PDF, an EN16931 CII XML, and a hybrid PDF/A-3 with the XML embedded.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `data` | object | ✅ | Full invoice data for ZUGFeRD/Factur-X generation |
| `environment` | string | — | Target environment (e.g. `"sandbox"`) |

This tool has no `integration` parameter — ZUGFeRD generation is local only, with no submit/delivery step.

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "user_agent": "pop-mcp",
  "user_agent_version": "1.0.0",
  "data": { "...invoice fields..." }
}
```

**Returns:** JSON with generation metadata and three Base64-encoded attachments:

```json
{
  "success": true,
  "data": {
    "valid": true,
    "profile": "EN16931",
    "attachments": {
      "pdf": { "filename": "...", "mime": "application/pdf", "content_base64": "..." },
      "xml": { "filename": "...", "mime": "application/xml", "content_base64": "..." },
      "hybrid_pdf": { "filename": "...", "mime": "application/pdf", "content_base64": "..." }
    },
    "validation": { "...": "..." },
    "errors": [],
    "warnings": []
  }
}
```

---

### `pop_get_invoice_status`

Retrieve the SdI processing status and notifications for a submitted invoice.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `uuid` | string (UUID) | ✅ | Invoice UUID returned by `pop_create_sdi_invoice` when `submit_to_sdi=true` |
| `response_format` | `"markdown"` \| `"json"` | — | Output format. Default: `"markdown"` |
| `environment` | string | — | Target environment |

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "integration": { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
}
```

**SdI notification statuses:** `pending` · `accepted` · `rejected` · `delivery`

> SdI processing is asynchronous and can take minutes to hours. Retry if no notifications are returned yet.

---

### `pop_get_peppol_document`

Retrieve a Peppol document from the network by UUID.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `uuid` | string (UUID) | ✅ | Peppol document UUID from `pop_create_peppol_invoice` |
| `zone` | string (2 chars) | — | Country code of the Peppol access point (e.g. `"BE"` for Belgium). Required for some regions. |
| `response_format` | `"markdown"` \| `"json"` | — | Output format. Default: `"markdown"` |
| `environment` | string | — | Target environment |

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "integration": { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "zone": "IT" }
}
```

> `zone` is omitted from the payload if not provided.

---

### `pop_get_sdi_document`

Retrieve an archived SdI (FatturaPA) document from POP storage by UUID.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `uuid` | string (UUID) | ✅ | SdI document UUID |
| `response_format` | `"markdown"` \| `"json"` | — | Output format. Default: `"markdown"` |
| `environment` | string | — | Target environment |

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "integration": { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
}
```

Requires: Basic+ plan with active SdI integration.

---

### `pop_verify_sdi_document`

Validate an SdI XML document for compliance before submission. Does not submit the document.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `xml_base64` | string | ✅ | The SdI XML document encoded as a Base64 string |
| `environment` | string | — | Target environment |

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "skip_business_check": true,
  "integration": { "xml": "<base64-encoded-xml-string>" }
}
```

**Validation checks performed:** XML schema conformance · fiscal code format · VAT number validity · required field presence · amount consistency

Requires: Basic+ plan with active SdI integration and registered business.

---

### `pop_preserve_document`

Archive an SdI document in certified long-term digital storage (conservazione sostitutiva). Italian law requires invoices to be preserved for 10 years.

**MCP inputs:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `uuid` | string (UUID) | ✅ | UUID of the SdI document to archive |
| `environment` | string | — | Target environment |

**API payload sent:**

```json
{
  "license_key": "YOUR_LICENSE_KEY",
  "integration": { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
}
```

> **Important:** Only call this tool when `pop_get_invoice_status` returns status `RC` (Ricevuta di Consegna) or `MC` (Mancata Consegna). Do not call for statuses `NS`, `EC`, `SE`, or `DT`.

Requires: Basic+ plan with active SdI integration.

---

## Usage Examples

### Generate a Simple Italian Invoice (XML Only)

Ask your AI assistant:

> "Create a FatturaPA invoice for 1000€ + 22% VAT to Rossi SRL (VAT IT12345678901, Milan). My company is Bianchi SRL (VAT IT98765432109, Rome), using payment method bank transfer to IBAN IT60X0542811101000000123456."

### Submit Invoice to SdI

> "Create and submit to SdI an invoice #45 for consulting services, 500€ + 22% VAT to customer Mario Rossi (fiscal code RSSMRA80A01H501U) in Rome."

### Check Invoice Status After Submission

> "What's the status of SdI invoice with UUID abc123-def456-...?"

### Generate PDF with Email Delivery

> "Create a PDF invoice for order #123 and email it to customer@example.com."

### Verify SdI Document Before Sending

> "Verify SdI document with UUID abc123-... for compliance before submission."

---

## Plan Requirements

| Feature | Free | Basic/Growth | Pro |
|---------|------|-------------|-----|
| XML generation (local) | ✅ | ✅ | ✅ |
| PDF generation | ✅ | ✅ | ✅ |
| SdI submission | ❌ | ✅ | ✅ |
| Peppol submission | ❌ | ✅ | ✅ |
| PDF email delivery | ❌ | ✅ | ✅ |
| SdI document verification | ❌ | ✅ | ✅ |
| Document preservation | ❌ | ✅ | ✅ |

---

## Testing

### MCP Inspector (Interactive)

```bash
npm run inspector
# or
npx @modelcontextprotocol/inspector dist/cli.js
```

### Quick Smoke Test

```bash
POP_API_KEY=your_key node -e "
import('./dist/cli.js').catch(e => {
  if (e.message.includes('stdin')) process.exit(0);
  console.error(e); process.exit(1);
});
"
```

### Test Tool Schema Listing

```bash
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | POP_API_KEY=test node dist/cli.js
```

---

## Development

```bash
# Run with auto-reload
npm run dev

# Build
npm run build

# Clean build artifacts
npm run clean
```

---

## Invoice Data Structure

The `data` parameter for invoice creation follows the FatturaPA structure:

```
data
├── id                    Invoice/order ID (numeric)
├── filename              Output filename without extension (e.g. 'IT99900088876_00009')
├── type                  "invoice" | "credit_note"
├── version               "FPR12" | "FPA12"
├── sdi_type              7-char SDI code ('0000000' for private individuals)
├── customer_type         "private" | "company" | "freelance" | "pa"
├── nature                VAT exemption code (required when rate is 0%, e.g. 'N2.1', 'N6.1')
├── transmitter_data
│   ├── transmitter_id    { country_id, id_code }
│   ├── progressive       Transmission progressive ID (e.g. '00001')
│   ├── transmitter_format  "FPR12" | "FPA12"
│   ├── sdi_code          7-char code
│   ├── transmitter_contact { phone, email }
│   └── recipient_pec     PEC email (alternative to sdi_code)
├── transfer_lender       Supplier/seller
│   ├── personal_data     { tax_id_vat: { country_id, id_code, tax_regime }, company_name }
│   ├── place             { address, zip_code, city, province_id, country_id }
│   └── contact           { phone, email }
├── transferee_client     Customer/buyer
│   ├── personal_data     { tax_id_vat, tax_id_code (fiscal code for IT private), company_name }
│   └── place             { address, zip_code, city, province_id, country_id }
├── invoice_body
│   ├── general_data      { doc_type (TD01|TD04), date (YYYY-MM-DD), invoice_number, currency }
│   └── total_document_amount
├── order_items[]
│   ├── description, quantity, unit
│   ├── unit_price, total_price
│   ├── rate              VAT rate as string (e.g. '22.00')
│   ├── total_tax         VAT amount (number)
│   └── item_type         "product" | "shipping" | "fee"
├── payment_data
│   ├── terms_payment     TP01 (instalment) | TP02 (full) | TP03 (advance)
│   ├── payment_details   MP01 (Cash) | MP02 (Check) | MP05 (Bank Transfer) | MP08 (Credit Card) | ...
│   ├── payment_amount
│   ├── beneficiary       Required for MP05 (bank transfer)
│   ├── financial_institution  Required for MP05
│   └── iban              Required for MP05
├── purchase_order_data   (optional) { id, date }
├── connected_invoice_data[]  (required for credit notes) { id, date }
├── overrides             (optional) { language, bollo_force_apply }
└── pdf                   (only for pop_create_pdf_invoice)
    ├── doc_type_title
    ├── logo_url
    ├── head              { store_info_address, billing[], shipping[] }
    ├── total_tax
    ├── email_invoice     { to[] (max 3), from }
    └── footer_text
```

---

## Error Reference

| Error Code | Meaning | Solution |
|-----------|---------|---------|
| `unauthorized_user` | Invalid license key | Check `POP_API_KEY` |
| `insufficient_level` | Plan too low | Upgrade POP plan |
| `business_not_registered` | No business profile | Register on popapi.io |
| `integration_inactive` | SdI/Peppol not enabled | Activate on popapi.io |
| `pop_api_email_limit` | >3 email recipients | Reduce to max 3 |
| `pop_api_email_not_allowed` | Plan doesn't allow email | Upgrade to Basic+ |

---

## Related Projects

- [n8n-nodes-pop](https://github.com/getpopapi/n8n-nodes-pop) — n8n community nodes for POP
- [POP](https://popapi.io) — Official website
- [API Documentation](https://documenter.getpostman.com/view/41622997/2sAYkLmGT8) — Postman docs

---

## License

MIT © [getpopapi](https://github.com/getpopapi)

TDQS

A4/5.0

Scored across 16 tools

Disambiguation4/5

Most tools have distinct purposes based on their target invoice format or operation. Potential confusion exists between pop_get_invoice_status and pop_get_sdi_document, but descriptions clearly differentiate status polling from document retrieval. Onboarding tools are distinctly sequenced.

Naming Consistency5/5

All tools follow a consistent pop_ prefix with snake_case. Create tools follow pop_create_<format>_invoice, get tools use pop_get_<resource>, and onboarding tools are grouped as pop_onboarding_*. The naming pattern is predictable and uniform.

Tool Count4/5

With 16 tools, the server is at the high end of the ideal range, but each tool serves a distinct purpose across multiple invoice formats and an onboarding sequence. The count is justified for the domain's breadth.

Completeness3/5

The server covers SdI and Peppol well with create/status/retrieve/verify operations, but lacks equivalent status and verification tools for KSeF and ZUGFeRD. Generic listing or cancellation tools are missing, and credit note support is inconsistent across formats.

Maintenance

ActivityMaintained
ResponsivenessNo issues