# Peppol e-invoicing checker — participant lookup (`kondasviktor/peppol-e-invoicing-participant-checker`) Actor

Check if a customer or supplier is registered on Peppol and which e-invoice document types they accept. Direct SML/SMP lookup, access point and certificate details, Directory business card, change tracking.

- **URL**: https://apify.com/kondasviktor/peppol-e-invoicing-participant-checker.md
- **Developed by:** [Viktor Kondas](https://apify.com/kondasviktor) (community)
- **Categories:** Business, Automation, AI
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 participant checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Peppol e-invoicing checker — participant lookup

**Check whether a customer or supplier is registered on Peppol — and which e-invoice documents they can receive.** Paste Peppol IDs or VAT numbers (or search by company name) and get one answer per company: registered or not, the Peppol ID, whether they accept Peppol BIS Billing 3.0 invoices, their access point and certificate dates, and the business card they published. JSON, CSV or Excel, via API, schedules, n8n, Make, Zapier and AI agents (MCP). **$0.01 per registered participant found** — "not registered" answers are free — no subscription.

> Independent tool, not affiliated with OpenPeppol. It reads the public Peppol network (SML DNS, the participant's own SMP) and the public Peppol Directory — no login, no private data.

### What does Peppol e-invoicing checker do?

- **Asks the Peppol network itself.** Registration is decided by the Peppol SML (DNS) and the participant's SMP — the same lookup an access point does before it sends an invoice. The Peppol Directory is only used for the business card, because publishing there is optional.
- **Works from the identifier you have.** A Peppol ID, a **VAT number** (e.g. `BE0123456789`, `NO974760673MVA`), a national **company id** + country, or just a **company name**. For VAT numbers and company ids the Actor works out every Peppol identifier that company could be registered under (VAT scheme, national registry scheme, …) and checks them all.
- **Tells you what they can receive**: invoices, credit notes, orders, despatch advices, invoice responses, and whether Peppol BIS Billing 3.0, XRechnung or PINT is supported.
- **Shows access point health**: access point host, transport (AS4/AS2), certificate expiry — with a warning before invoices start bouncing.
- **Remembers the last run** and reports `newly_registered`, `deregistered`, `document_types_changed` or `endpoint_changed` — schedule it weekly on your supplier list.
- **Never guesses.** A DNS or SMP failure is reported as a failed lookup (and is free), never as "not registered".

### Who is it for?

| You are… | You use it to… |
|---|---|
| AR / billing team, shared service centre | Check which customers can receive Peppol e-invoices before a mandate or a roll-out wave |
| AP team | Find out which suppliers are reachable on Peppol and which still send PDFs |
| ERP / e-invoicing integrator | Verify a Peppol ID before go-live, test on the Peppol test network, clean partner master data in bulk |
| Finance data / master data team | Add "Peppol-ready" and the Peppol ID to the customer and vendor master — pairs with VAT validation |

### Ready-made examples (one click)

| Example | What you get |
|---|---|
| [Check if customers are on Peppol from VAT numbers](https://apify.com/kondasviktor/peppol-e-invoicing-participant-checker/examples/check-customers-on-peppol-by-vat) | One row per VAT number, every possible Peppol identifier tried |
| [Verify a Peppol ID before sending an e-invoice](https://apify.com/kondasviktor/peppol-e-invoicing-participant-checker/examples/verify-peppol-id-before-sending-invoice) | Registered? BIS Billing 3.0? Access point and certificate dates |
| [Find Peppol participants by company name](https://apify.com/kondasviktor/peppol-e-invoicing-participant-checker/examples/find-peppol-participants-by-company-name) | Directory matches confirmed against the live network |
| [Monitor when suppliers become reachable on Peppol](https://apify.com/kondasviktor/peppol-e-invoicing-participant-checker/examples/monitor-supplier-peppol-readiness) | Schedule weekly, get `newly_registered` / `deregistered` |
| [Check Peppol access point certificate expiry](https://apify.com/kondasviktor/peppol-e-invoicing-participant-checker/examples/check-peppol-access-point-certificate-expiry) | Partners whose certificate or registration is about to expire |

### How to use it

1. Paste Peppol IDs or VAT numbers into **Peppol IDs or VAT numbers** (one per line) — or open an example above.
2. Optional: add **Records** (JSON) with your own `reference`, company ids or names.
3. Set **Max paid results** — it is also your cost cap. Click **Start**. Filter the dataset by `verdict`, or download it.

### Input

| Field | Required | Description |
|---|---|---|
| `participants` | one of these two | Peppol IDs (`0088:5790000436507`) or VAT numbers with country prefix (`BE0123456789`), one per line |
| `records` | one of these two | JSON objects: `reference` (your customer number, echoed back), `peppolId`, `vatNumber`, `companyId` + `country`, `scheme`, `name` (+ `country`) |
| `maxParticipants` | no | Cap on paid results (registered participants) and cost. Default 100 |
| `network` | no | `production` (default) or `test` (Peppol test network) |
| `includeBusinessCard` | no | Company name, country, address line, websites from the Peppol Directory. Default on |
| `includeEndpointDetails` | no | Access point, transport, certificate dates. Default on |
| `includeContacts` | no | Contact persons from business cards. **Off by default** (personal data) |
| `maxCandidatesPerName` | no | Matches to verify per name search. Default 3 |
| `expiryWarningDays` | no | Warn when a certificate or registration expires within this many days. Default 30 |
| `trackHistory` / `historyStoreName` | no | Compare with the previous run of the same list. History lives in a key-value store in **your** account |

Records example:

```json
[
  { "reference": "C-1001", "country": "NO", "companyId": "974760673" },
  { "reference": "C-1002", "vatNumber": "BE0123456789" },
  { "reference": "C-1003", "peppolId": "0088:5790000436507" },
  { "reference": "C-1004", "name": "Example Trading", "country": "DE" }
]
```

### Output

Example row (fictitious company — your rows contain the real data):

```json
{
  "reference": "C-1002",
  "input": "BE0123456789",
  "queryType": "vat-number",
  "network": "production",
  "verdict": "registered",
  "registered": true,
  "peppolId": "iso6523-actorid-upis::0208:0123456789",
  "participantScheme": "0208",
  "participantSchemeName": "Belgian enterprise number",
  "alsoRegisteredAs": ["iso6523-actorid-upis::9925:BE0123456789"],
  "canReceiveInvoice": true,
  "canReceiveBisBillingInvoice": true,
  "profiles": ["Peppol BIS Billing 3.0", "Peppol BIS Order 3"],
  "documentTypeCount": 4,
  "accessPointHost": "ap.example.com",
  "transportProfile": "peppol-transport-as4-v2_0",
  "certificateValidUntil": "2027-03-01T00:00:00.000Z",
  "certificateDaysLeft": 118,
  "endpointWarning": null,
  "directoryListed": true,
  "businessName": "Example Trading BV",
  "change": "unchanged",
  "explanation": "Registered on Peppol as Example Trading BV (0208:0123456789) [Belgian enterprise number]. It can receive invoices (Peppol BIS Billing 3.0), credit notes, orders via ap.example.com (peppol-transport-as4-v2_0). Access point certificate valid until 2027-03-01.",
  "sourceUrl": "https://smp.example.com/iso6523-actorid-upis%3A%3A0208%3A0123456789",
  "status": "ok",
  "scrapedAt": "2026-11-27T08:00:00.000Z"
}
```

Each row also lists `documentTypes` (id, family, profile), `capabilities`, `schemesTried` (every identifier that was probed and what the network answered), `smpUrl` and the full `businessCards`.

| Verdict | Meaning | Charged? |
|---|---|---|
| `registered` | In the Peppol SML; document types read from the participant's SMP | **Yes** |
| `not_registered` | The SML has no participant for the identifier(s) tried — a definitive answer (`status: not_found`) | No — free |
| `registered_unconfirmed` | In the SML, but its SMP did not answer — document types unknown | No (`status: partial`) |
| `lookup_failed` | DNS/SMP/Directory trouble — says nothing about registration | No |
| `invalid_input` / `unsupported_country` | Could not be checked; the explanation says why | No |
| `no_match` | Name search found nothing in the Directory | No |

### How much does it cost?

| Event | Price | When |
|---|---|---|
| Actor start | Apify default | Once per run |
| Participant checked | $0.01 | Each participant found **registered** (document types read from its SMP) |

**100 registered participants ≈ $1.00 · 1,000 ≈ $10.** Participants that are **not registered**, invalid input, unsupported countries, DNS/SMP failures and name searches without a match are **not charged** — you only pay when there is a registration to report. Higher Apify plans get Store discounts automatically. Set **Max cost per run** in the run options for a hard budget.

### Schedule it

Weekly (Monday 07:00) on your supplier and customer master data is enough to catch registrations and certificate problems. Use a different **History store name** for each list.

### Use with AI agents (MCP)

> "Use kondasviktor/peppol-e-invoicing-participant-checker to check which of these 40 customers can receive Peppol BIS Billing 3.0 invoices: …"

### FAQ

**What is Peppol?** An international network for exchanging e-invoices and other business documents. A company registers its identifier with a Peppol access point; senders look the participant up in the Peppol SML and the participant's SMP to find where to deliver.

**Does "not registered" mean the company cannot be reached on Peppol?** (Free — you are not charged for it.) Under the identifiers we tried, yes. A company can be registered under a different identifier — for example a GLN — that cannot be derived from a VAT number. If you know its Peppol ID, pass it and the answer is exact.

**Is "not listed in the Peppol Directory" the same as "not registered"?** No. Publishing in the Directory is optional. Registration is decided by the SML; the Directory only supplies the business card.

**Does "registered" mean they will accept my invoice?** It means documents can be delivered to them over Peppol and which document types they accept. Business rules (PO numbers, routing identifiers) are between you and your customer.

**How is this different from VAT validation (VIES)?** VIES tells you whether a VAT number is valid. This tells you whether the company can *receive e-invoices over Peppol*. Use both — see [Company Data Verifier](https://apify.com/kondasviktor/company-data-verifier).

**How is this different from an access point provider?** Access point providers send and receive your invoices under a contract. This Actor only answers "can I reach them on Peppol, and how?" — before you send, and in bulk, for a cent.

**Which countries work?** Any identifier registered on the Peppol network. VAT numbers and company ids are converted automatically for most European countries; for other countries pass the Peppol ID.

**Test network?** Set **Peppol network** to `test` to look up participants on Peppol's test network.

**Something looks wrong.** Open an issue with the input and the `explanation` — fixes within 48 hours.

### Limitations

- Reads what the Peppol network publishes. It does not send documents, validate invoices or prove that an invoice will be accepted.
- SMP responses are not signature-verified in v1.
- Business cards exist only for participants that published one. Contact persons are off by default.
- The Peppol Directory is rate-limited, so business cards are fetched at a polite pace (about 1–2 per second).

### Related Actors

- [Company Data Verifier](https://apify.com/kondasviktor/company-data-verifier) — validate VAT numbers (VIES) and clean company master data
- [EU Omnibus Discount Checker](https://apify.com/kondasviktor/eu-omnibus-discount-checker) — audit EU shop discounts against the 30-day lowest price
- [Shopify Discount & Promo Tracker](https://apify.com/kondasviktor/shopify-discount-promo-tracker) — track sale depth on any Shopify store

***

Built by [Viktor Kondas](https://apify.com/kondasviktor) · [Vibe Coder's Life](https://vibecoderslife.com/?utm_source=apify\&utm_medium=readme\&utm_campaign=peppol-e-invoicing-participant-checker) · Custom integrations: hello@vibecoderslife.com

# Actor input Schema

## `participants` (type: `array`):

One per line. A Peppol ID looks like <code>0088:5790000436507</code> (four-digit scheme code, colon, identifier; <code>iso6523-actorid-upis::</code> in front is fine). A VAT number needs its country prefix, e.g. <code>BE0123456789</code> or <code>NO974760673MVA</code> — the Actor works out which Peppol identifiers that company could be registered under and checks them all. For national company ids or names use <b>Records</b> below.

## `records` (type: `array`):

Detailed entries as JSON objects, e.g. from your ERP export. Fields (all optional, use what you have): <code>reference</code> (your customer/supplier number — echoed back in the result), <code>peppolId</code>, <code>vatNumber</code>, <code>companyId</code> + <code>country</code> (e.g. Norwegian organisation number, Dutch KvK, French SIREN, Belgian enterprise number…), <code>scheme</code> (four-digit Peppol scheme code to use with <code>companyId</code>), <code>name</code> (+ optional <code>country</code>) to search the Peppol Directory by company name. Example: <code>{"reference": "C-1001", "country": "NO", "companyId": "974760673"}</code>

## `maxParticipants` (type: `integer`):

Hard cap on paid results — participants found registered. Free rows (not registered, invalid input, lookup failures) do not count. This is also your cost cap: 100 results = $1.00.

## `network` (type: `string`):

<b>production</b> is the live Peppol network. <b>test</b> uses Peppol's test network (SMK) — for ERP integrators checking their test setup.

## `includeBusinessCard` (type: `boolean`):

Company name, country, address line, websites and registration date, when the participant published them (publication is optional). One extra, rate-limited request per result.

## `includeEndpointDetails` (type: `boolean`):

Access point host, transport profile (AS4 / AS2) and certificate validity dates, with a warning when the certificate or SMP registration is expired or about to expire.

## `includeContacts` (type: `boolean`):

Off by default: Directory business cards may contain names, e-mail addresses and phone numbers of individuals. Only switch on if you have a lawful basis to process them.

## `maxCandidatesPerName` (type: `integer`):

For records with a <code>name</code>: how many Directory matches to verify (each verified match is one result).

## `expiryWarningDays` (type: `integer`):

Flag access point certificates and SMP registrations that expire within this many days.

## `trackHistory` (type: `boolean`):

Compare with the previous run of the same list and report <code>newly_registered</code>, <code>deregistered</code>, <code>document_types_changed</code> or <code>endpoint_changed</code>. The history is stored in a key-value store in YOUR account.

## `historyStoreName` (type: `string`):

Name of the key-value store that holds the previous results. Use a different name per list you monitor. 3–63 characters: lowercase letters, digits and hyphens.

## Actor input object example

```json
{
  "participants": [
    "0192:991825827",
    "0192:974760673"
  ],
  "records": [],
  "maxParticipants": 10,
  "network": "production",
  "includeBusinessCard": true,
  "includeEndpointDetails": true,
  "includeContacts": false,
  "maxCandidatesPerName": 3,
  "expiryWarningDays": 30,
  "trackHistory": true,
  "historyStoreName": "peppol-participant-history"
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "participants": [
        "0192:991825827",
        "0192:974760673"
    ],
    "maxParticipants": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("kondasviktor/peppol-e-invoicing-participant-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "participants": [
        "0192:991825827",
        "0192:974760673",
    ],
    "maxParticipants": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("kondasviktor/peppol-e-invoicing-participant-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "participants": [
    "0192:991825827",
    "0192:974760673"
  ],
  "maxParticipants": 10
}' |
apify call kondasviktor/peppol-e-invoicing-participant-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kondasviktor/peppol-e-invoicing-participant-checker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/HJPVV1bffXKRgf89S/builds/BwygBdN1vrEi7zITU/openapi.json
