# Poland Company Lookup (NIP / KRS) (`d_northlist/pl-company-lookup`) Actor

Send a Polish NIP or KRS number — get one normalized JSON profile. Optionally check a bank account against Biała Lista before you pay.

- **URL**: https://apify.com/d\_northlist/pl-company-lookup.md
- **Developed by:** [Northlist](https://apify.com/d_northlist) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 company profiles

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Poland Company Lookup (NIP / KRS)

Look up a Polish company or sole trader with a **NIP** or **KRS** number and get one English-friendly JSON profile: legal name, legal form, status, and registered address.

Data comes live from official registers — **KRS**, **CEIDG**, and the Ministry of Finance **VAT whitelist (Biała Lista)**. You do not need to know which register to call.

Optionally pass the supplier’s **bank account**. The Actor checks whether that account is assigned to the NIP on Biała Lista and returns a `paySafe` verdict before you pay.

**Store ID:** [`northlist/pl-company-lookup`](https://apify.com/northlist/pl-company-lookup)

### Why use it

Foreign invoicing, ERP, KYB, and CRM tools collect a Polish NIP or KRS at signup. Those numbers sit in different government systems, often with Polish-only portals and a sales process for an API key.

This Actor is the self-serve path: one input, one JSON shape, pay per lookup, ready for n8n / Make / your backend.

Typical jobs:

- **Onboarding** — store legal name, status, and address when a Polish customer or supplier signs up.
- **KYB / AML** — add a normalized Polish profile next to other country registries.
- **CRM enrichment** — new row in HubSpot / Pipedrive → this Actor → write `name`, `status`, `address` back.
- **Pay-safe** — invoice NIP + IBAN + amount → `paySafe.verdict`. Block or split-pay on `DO_NOT_PAY`. Keep `requestId` on the payment file.

### What you send vs what we query

| You send | Who it is | Source | Extra key? |
| --- | --- | --- | --- |
| KRS number | Company (sp. z o.o., S.A., …) | National Court Register | No |
| Company NIP | Same companies | VAT whitelist → KRS extract | No |
| Sole-trader NIP (JDG) | CEIDG | CEIDG API | Yes — free JWT (see below) |
| Any of the above + `bankAccount` | Pay-safe | Profile, then Biała Lista **check** | No |

Up to **30** identifiers per run (`identifiers`). One dataset item per identifier.

### Input

| Field | Required | What it does |
| --- | --- | --- |
| `identifier` | One of `identifier` / `identifiers` | NIP (10 digits) or KRS. Spaces, dashes, and a `PL` prefix are stripped. |
| `identifiers` | One of `identifier` / `identifiers` | Batch, max 30. |
| `identifierType` | No | `auto` (default), `nip`, or `krs`. |
| `CEIDG_API_TOKEN` | Only for JDG NIP | Secret JWT from [dane.biznes.gov.pl](https://dane.biznes.gov.pl/pl/dane-po-api). Not needed for KRS or company NIP. |
| `bankAccount` | No | Polish NRB (26 digits) or IBAN. Turns on pay-safe. |
| `checkDate` | No | `YYYY-MM-DD` (Europe/Warsaw). Defaults to today. Used only with `bankAccount`. |
| `amountPln` | No | Invoice gross in PLN. Over 15 000 with an unassigned account → `DO_NOT_PAY`. |
| `includeRawSource` | No | Debug: attach upstream JSON as `raw`. PESEL, IBANs, and person names are stripped. |

### Output

Every run returns one object per identifier. Unknown numbers come back as `status: "not_found"` (still a billed lookup). A bad NIP checksum on a single `identifier` **fails the run** and is **not** billed.

```json
{
  "identifier": {
    "input": "0000028860",
    "type": "krs",
    "krs": "0000028860",
    "nip": "7740001454",
    "regon": "610188201"
  },
  "name": "ORLEN SPÓŁKA AKCYJNA",
  "legalForm": "S.A.",
  "status": "active",
  "address": {
    "street": "CHEMIKÓW 7",
    "city": "PŁOCK",
    "postalCode": "09-411",
    "country": "PL"
  },
  "registeredSince": "2001-07-19",
  "representatives": "redacted_in_source_api",
  "source": { "krs": true, "ceidg": false, "whitelist": false },
  "fetchedAt": "2026-08-30T14:00:00.000Z",
  "warnings": []
}
```

`status` is one of: `active`, `deregistered`, `suspended`, `unknown`, `not_found`.

Board member names and PESEL are hidden in the official KRS JSON API. This Actor always returns `"representatives": "redacted_in_source_api"`. Identity lookup never copies bank accounts or personal names from the VAT whitelist search.

#### Pay-safe (`paySafe`)

Present only when you set `bankAccount`. Same dataset item — no second Actor.

| `verdict` | Meaning |
| --- | --- |
| `PAY` | Account is assigned to this NIP on the check date. |
| `DO_NOT_PAY` | Account is **not** assigned, and the amount is missing or over 15 000 PLN gross. Polish VAT rules can make that transfer expensive; treat this as a hard stop or use split payment. |
| `BELOW_THRESHOLD` | Account not assigned, but `amountPln` is 15 000 or less. |
| `FOREIGN_IBAN_EXCLUDED` | Not a Polish NRB/IBAN — Ministry check is not used. |
| `NIP_UNAVAILABLE` | No NIP to check (for example a KRS-only miss). Not billed as pay-safe. |
| `CHECK_UNAVAILABLE` | Ministry API rate limit or error. Not billed as pay-safe; retry later. |

You get `accountLast4`, `accountAssigned`, and the official Ministry `requestId`. The full IBAN is never returned. `paySafe` is evidence from the Ministry API, not a tax ruling.

### Pricing

Pay per event (FREE tier):

| What you did | Event | Price |
| --- | --- | --- |
| Actor started | `apify-actor-start` | $0.00005 |
| One company profile (including `not_found` and cache hits) | `lookup` | **$0.008** ($8 / 1,000) |
| Biała Lista bank-account check | `lookup-whitelist` | **$0.025** |

A profile-only run is about **$0.008**. Profile + pay-safe is about **$0.033**.

**Not billed:** invalid NIP checksum, invalid bank account, empty input, or REGON as input (the run fails). Pay-safe is not billed on `NIP_UNAVAILABLE` or `CHECK_UNAVAILABLE`.

Successful profiles are cached for 7 days; genuine not-found for 1 day. Pay-safe for “today” expires at midnight Warsaw.

### How to run

#### Apify Console

Open the Actor, paste a NIP or KRS into **Polish identifier**, click **Start**. Try KRS `0000028860` or company NIP `7740001454`.

#### API

Replace `APIFY_TOKEN` with your [Apify API token](https://console.apify.com/account/integrations). This waits for the run and returns the dataset JSON:

```bash
curl "https://api.apify.com/v2/acts/northlist~pl-company-lookup/run-sync-get-dataset-items?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"identifier":"0000028860","identifierType":"krs"}'
```

Company by NIP (no CEIDG token):

```json
{ "identifier": "7740001454", "identifierType": "nip" }
```

Pay-safe (profile + whitelist check):

```json
{
  "identifier": "7740001454",
  "identifierType": "nip",
  "bankAccount": "PL40124010661111001156329830",
  "amountPln": 20000
}
```

#### n8n / Make

1. Use the **Apify** node (or HTTP Request).
2. Actor: `northlist/pl-company-lookup`.
3. Operation: run Actor and get dataset items.
4. Body:

```json
{
  "identifier": "{{ $json.nip }}",
  "identifierType": "auto"
}
```

Map `name`, `status`, and `address` onto the CRM record.

To block a supplier payment, add `bankAccount` and `amountPln`, then branch on `paySafe.verdict === "DO_NOT_PAY"`. Store `paySafe.requestId` on the invoice.

### Sole traders (CEIDG)

Company NIPs and all KRS lookups work with no extra key.

For a **JDG** NIP, register a free JWT at [dane.biznes.gov.pl](https://dane.biznes.gov.pl/pl/dane-po-api) and paste it into the secret input `CEIDG_API_TOKEN`. Without it, a sole-trader lookup cannot hit CEIDG.

### Limits and scope

- **REGON** is not accepted as input in this version.
- Max **30** identifiers per run.
- KRS JSON does not include unredacted board names; we do not scrape PDFs to restore them.
- This is not an official court extract (`odpis`) and not KSeF.
- Ministry daily quotas apply on the VAT whitelist (search vs check are separate). If you see `CHECK_UNAVAILABLE`, wait and retry; that row is not billed as pay-safe.

# Actor input Schema

## `identifier` (type: `string`):

NIP (10 digits) or KRS number (up to 10 digits). Spaces, dashes, and a PL prefix are stripped. Use this or identifiers. REGON is not supported in this version.

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

Up to 30 NIP or KRS values in one run. Combined with identifier and de-duplicated. Each result is one dataset item (one lookup charge). Invalid items are returned unbilled.

## `identifierType` (type: `string`):

auto: detect NIP vs KRS. nip: CEIDG then VAT whitelist → KRS. krs: National Court Register only.

## `includeRawSource` (type: `boolean`):

If true, add a `raw` field with upstream KRS, CEIDG, and/or whitelist JSON. PESEL, IBANs, and natural-person names are stripped. For debugging only. Bypasses cache.

## `CEIDG_API_TOKEN` (type: `string`):

Bearer JWT from https://dane.biznes.gov.pl/pl/dane-po-api. Required only for sole-trader (JDG) NIP lookups. Company NIPs use the public VAT whitelist (no key). Leave empty for KRS and company-NIP runs. Stored encrypted.

## `bankAccount` (type: `string`):

Polish NRB (26 digits) or IBAN. When set, the Actor checks whether this account is assigned to the NIP on Biała Lista. Stored encrypted in the run input; the dataset only returns the last four digits.

## `checkDate` (type: `string`):

Date for the Biała Lista check, YYYY-MM-DD, Europe/Warsaw (for example 2026-08-31). Defaults to today. Ignored unless bankAccount is set. Not in the future; at most 5 years back.

## `amountPln` (type: `number`):

Optional invoice gross in PLN. Used only with bankAccount. Amounts over 15000 can trigger whitelist sanctions if the account is not assigned. Below 15000, a mismatch is BELOW\_THRESHOLD.

## Actor input object example

```json
{
  "identifier": "0000028860",
  "identifierType": "auto",
  "includeRawSource": false
}
```

# Actor output Schema

## `companyProfiles` (type: `string`):

Default dataset: one JSON item per NIP or KRS lookup, including not-found rows.

# 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 = {
    "identifier": "0000028860"
};

// Run the Actor and wait for it to finish
const run = await client.actor("d_northlist/pl-company-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 = { "identifier": "0000028860" }

# Run the Actor and wait for it to finish
run = client.actor("d_northlist/pl-company-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 '{
  "identifier": "0000028860"
}' |
apify call d_northlist/pl-company-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,d_northlist/pl-company-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/Gny21aCNQhRpyOis0/builds/aPd6sWwBGyciWUy0U/openapi.json
