# Peppol Directory Lookup — company records and document types (`fetchlab/peppol-lookup`) Actor

Find company records in the official Peppol Directory by VAT/enterprise number or name. Returns declared document types and explicit found/not-found/invalid-format/error states. Does not establish network reachability.

- **URL**: https://apify.com/fetchlab/peppol-lookup.md
- **Developed by:** [fetchlab](https://apify.com/fetchlab) (community)
- **Categories:** Business, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Peppol Directory Lookup — company records and declared document types

Find a company in the **official Peppol Directory** by VAT number, enterprise number or name, and read the document types declared on its business card. The Directory is voluntary and incomplete: **not found does not mean unreachable on Peppol**. This Actor does not query SML/SMP or verify delivery. [Official Directory specification](https://docs.peppol.eu/edelivery/directory/PEPPOL-EDN-Directory-1.1.1-2020-10-15.pdf).

Data comes live from the official **Peppol Directory** operated by OpenPeppol (directory.peppol.eu). No scraping, no cached copies.

### Why you need this

Belgian B2B e-invoicing requirements and the French reform create demand for structured invoice workflows, but national delivery requirements differ. This Actor verifies only the scope described below; it is not a legal or tax eligibility check. See the [Belgian official guidance](https://efacture.belgium.be/fr/article/quest-ce-quune-facture-electronique) and [French official guidance](https://www.impots.gouv.fr/facturation-electronique-et-plateformes-agreees).

Typical uses:

- **Accounting & ERP teams** — bulk-check a customer list before switching invoices from PDF to Peppol.
- **SaaS builders** — call it from your onboarding flow to retrieve the customer’s Directory business card and declared document types.
- **AI agents** — a single-purpose tool that returns a structured answer to "what does Directory publish about this company?".
- **Sales & compliance** — find out which companies in a country or sector are listed in Directory.

### Input

| Field | Description |
|---|---|
| `identifiers` | List of VAT numbers or enterprise numbers, one per line. Accepted formats: `BE0202239951`, `0202.239.951`, `0202239951`, `NL857982012B01`, `FR12345678901`, `DE123456789`, or a full Peppol ID such as `0208:0202239951`. Spaces, dots and dashes are ignored. |
| `names` | Optional list of company names to search (partial match). |
| `country` | Optional ISO country code (`BE`, `NL`, `FR`…) to narrow name searches. |
| `defaultCountry` | Country assumed for numbers typed without a prefix. Default `BE`. |
| `maxResultsPerName` | Max participants returned per name search (1–100, default 10). |
| `groupNameResults` | Name searches return one row per company, with every Peppol ID it is registered under in `participantIds` (default on). |
| `tryAllSchemes` | Countries have several Peppol identifier schemes (Belgium: `0208` enterprise number and `9925` VAT number). When on, all are tried until a match is found. |

Example:

```json
{
    "identifiers": ["BE0202239951", "0834.096.436", "NL857982012B01"],
    "names": ["proximus"],
    "country": "BE"
}
```

### Output

One record per identifier checked, and one per grouped company for name searches (unless grouping is disabled). `maxResultsPerName` limits participants before grouping; `totalMatches` is the raw participant count:

```json
{
    "type": "identifier",
    "input": "BE0202239951",
    "registered": true,
    "directoryStatus": "found",
    "networkReachability": "not-checked",
    "participantId": "0208:0202239951",
    "participantSchemeLabel": "BE:EN (enterprise number)",
    "entityName": "Proximus S.A.",
    "entityCountry": "BE",
    "registrationDate": "2025-06-02",
    "capabilities": {
        "acceptsInvoice": true,
        "acceptsCreditNote": true,
        "acceptsOrder": false,
        "acceptsDespatchAdvice": false,
        "acceptsBisBilling3": true
    },
    "documentTypes": [
        { "summary": "Invoice — Peppol BIS Billing 3.0", "document": "Invoice", "profile": "Peppol BIS Billing 3.0", "version": "2.1", "id": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1" },
        { "summary": "Credit note — Peppol BIS Billing 3.0", "document": "CreditNote", "profile": "Peppol BIS Billing 3.0", "version": "2.1", "id": "…" }
    ],
    "schemesTried": ["0208:0202239951"],
    "directoryUrl": "https://directory.peppol.eu/public/locale-en_US/menuitem-search?q=0208%3A0202239951",
    "checkedAt": "2026-09-13T17:40:00.000Z",
    "error": null
}
```

`directoryStatus` distinguishes `found`, `not-found`, `invalid-format` and `error`. The legacy `registered` flag is true only for a Directory match; never use false as a routing decision. `networkReachability` is always `not-checked`. Capabilities are declarations from Directory, not an independently verified SMP response.

### Supported countries and identifier schemes

Belgium (0208 enterprise number, 9925 VAT), Netherlands (0106 KvK, 9944 VAT, 0190 OIN), France (0009 SIRET, 0002 SIRENE, 9957 VAT), Germany (9930 VAT, 0204 Leitweg-ID), Italy (0211 Partita IVA, 0210 Codice Fiscale), Luxembourg, Austria, Denmark, Sweden, Norway, Finland, Spain, Portugal, Ireland, Poland, and every other EU/EEA country with a Peppol VAT scheme, plus Australia, New Zealand, Singapore, Japan and Malaysia. You can always pass a full `scheme:value` Peppol ID for anything else.

### Pricing

Pay per event: **USD 0.005 per identifier lookup** and **USD 0.01 per name search**. A name search is charged once regardless of returned rows. Prices are unchanged. Network latency and retries affect runtime.

When both `identifiers` and `names` are omitted, three demo identifiers are used. Supplying either field disables the demo; explicitly empty sources are rejected. For a name-only request, `{"names":["proximus"],"country":"BE"}` queries only that name.

### Using it from your code

```js
// Apify JS client
const run = await client.actor('fetchlab/peppol-lookup').call({
    identifiers: ['BE0202239951', 'NL857982012B01'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

```python
## Apify Python client
run = client.actor("fetchlab/peppol-lookup").call(run_input={"identifiers": ["BE0202239951"]})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

Works with the Apify API, the Apify MCP server (so AI agents can call it as a tool), Make, n8n, Zapier and scheduled runs.

### Notes and limits

- The Peppol Directory only lists participants whose Access Point publishes a "business card". A company can technically be reachable on Peppol without appearing in the Directory.
- The Directory enforces a limit of 2 requests per second; this Actor respects it and retries automatically on temporary errors.
- Data is returned as published by the Access Points; names and addresses are not normalised.

### Related

Looking for VAT validation (VIES), Belgian company data (BCE/KBO) or an e-invoice (UBL / Peppol BIS) validator? See the other Actors by [fetchlab](https://apify.com/fetchlab).

# Actor input Schema

## `identifiers` (type: `array`):

One value per line. Accepted formats: VAT number with country prefix (BE0202239951, NL123456789B01, FR12345678901, DE123456789), Belgian enterprise number (0202.239.951 or 0202239951), or a full Peppol participant ID (0208:0202239951). Spaces, dots and dashes are ignored.

## `names` (type: `array`):

Optional. Company names to search for (partial matches). Use the 'Country' field below to narrow the search. Each name returns up to 'Max results per name' participants.

## `country` (type: `string`):

Optional ISO 3166-1 alpha-2 country code (BE, NL, FR, DE…) to restrict name searches. Leave empty to search all countries.

## `defaultCountry` (type: `string`):

Country assumed for identifiers typed without a country prefix (e.g. '0202239951'). Default: BE (Belgian enterprise number).

## `maxResultsPerName` (type: `integer`):

Maximum number of participants fetched from the Directory for each name search (before grouping by company).

## `includeDocumentTypes` (type: `boolean`):

Include the raw Peppol document type identifiers next to the human-readable summary. Turn off for a lighter output.

## `tryAllSchemes` (type: `boolean`):

For each country several Peppol identifier schemes exist (e.g. Belgium: 0208 enterprise number and 9925 VAT). When on, all schemes are tried until a match is found. When off, only the most common scheme is tried (faster).

## `groupNameResults` (type: `boolean`):

The Peppol Directory often lists the same company under several identifiers (enterprise number, VAT number). When on, a name search returns one row per company with all its Peppol IDs in 'participantIds'. Turn off to get one row per identifier.

## Actor input object example

```json
{
  "country": "BE",
  "defaultCountry": "BE",
  "maxResultsPerName": 10,
  "includeDocumentTypes": true,
  "tryAllSchemes": true,
  "groupNameResults": true
}
```

# Actor output Schema

## `results` (type: `string`):

All results as JSON items.

# 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 = {
    "country": "BE"
};

// Run the Actor and wait for it to finish
const run = await client.actor("fetchlab/peppol-lookup").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 = { "country": "BE" }

# Run the Actor and wait for it to finish
run = client.actor("fetchlab/peppol-lookup").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 '{
  "country": "BE"
}' |
apify call fetchlab/peppol-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fetchlab/peppol-lookup"
        }
    }
}
```

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/wYfrs4XVdktuSvZ2p/builds/pkEz6dDoos2QJzLP6/openapi.json
