# Polish VAT & Bank Account Checks with Receipt IDs (`thatmike1/pl-vat-payment-proof`) Actor

Check supplied Polish NIP/account pairs against the official VAT White List. Export invoice-linked results with separate Ministry request IDs and explicit incomplete-check diagnostics. Small batches, no tax-compliance guarantee.

- **URL**: https://apify.com/thatmike1/pl-vat-payment-proof.md
- **Developed by:** [Michal Pšenčík](https://apify.com/thatmike1) (community)
- **Categories:** Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

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

## Polish VAT & Bank Account Checks with Receipt IDs

Check up to 30 supplied invoice/NIP/bank-account/date entries against the Polish Ministry of Finance VAT White List. Each complete receipt includes the NIP profile and a separate authoritative account assignment check, with their two official request IDs retained separately. Export complete rows as JSON or CSV through the Apify dataset. Free KV `SUMMARY` reports failures, incomplete checks and every original input index.

This is a small payment-batch export for companies with a nonempty 10-digit KRS. Missing KRS produces `unsupported_subject_scope`; it does not classify the subject as a person. This actor is independent of the Ministry and is not officially endorsed.

```json
{
    "payments": [
        {
            "invoiceReference": "DEMO-INVOICE-001",
            "nip": "7740001454",
            "bankAccount": "PL30102010260000140203550589"
        }
    ],
    "maxResults": 30,
    "requestIntervalMs": 2000
}
```

`payments` is required with 1–30 entries before deduplication; total input must fit 32 KiB UTF-8. Unknown fields are rejected. NIP/account must be strings; optional uppercase `PL`, ASCII spaces and hyphens are normalized and both checksums validated. Invoice references are echoed exactly: nonblank, up to 128 Unicode code points, with no control characters. Per-entry `date` is optional, defaults to today's date in `Europe/Warsaw` frozen at run start, and must be a real `YYYY-MM-DD` between today minus 365 days and today inclusive. Invalid entries never cause source requests; other valid entries can proceed. Invalid top-level input aborts the run.

`maxResults` is 1–30 (default 30), limiting delivered unique rows. Entries with identical normalized NIP/account/date share one row, with `inputIndexes` and distinct `invoiceReferences` in original order. Different accounts for the same NIP/date reuse a successful profile receipt within the run. `requestIntervalMs` is 1200–5000 (default 1200); the runtime conservatively enforces at least 2000 ms idle after each response, including retries and redirects. Bigger intervals or slow responses may leave a batch incomplete.

Each complete row includes `schemaVersion`, `normalizationVersion`, `checkKey`, `recordId`, `inputIndexes`, `invoiceReferences`, `nip`, `bankAccountNrb`, `requestedDate`, `subjectName`, `krs`, `vatStatusAsReturned`, `hasVirtualAccounts`, `accountAssigned`, `observationHash`, `vatStatusTemporalBasis`, `lookupReceipt`, `accountCheckReceipt` and `warnings`. Each receipt contains the official `requestId`, raw `requestDateTimeRaw`, `timeZone:null`, independently observed UTC `fetchedAt`, exact `sourceUrl` and SHA256 of the raw decoded response bytes. Full source profiles, addresses, PESEL, REGON, people arrays and account lists are excluded from production storage.

`accountAssigned` is the source's `TAK` or `NIE` answer for your supplied pair/date, including virtual accounts. A negative answer is a complete paid receipt. It is never inferred from account-list membership. VAT status is returned as `Czynny`, `Zwolniony` or `Niezarejestrowany`, with `vatStatusTemporalBasis: "source_response_unverified"`. Historical VAT-status semantics have not been independently verified. The two requests are separate observations and are not an atomic government certificate. Source timestamp timezone is unspecified, so it remains raw without conversion, including ambiguous autumn clock hours.

`checkKey` hashes the normalized pair/date; `recordId` also includes both official IDs. `observationHash` covers the eight factual fields, excluding invoice references, times and receipt IDs. Consumers can compare facts across runs: a correction changes the hash, a timestamp-only change does not. Every new run fetches fresh receipts; unchanged results are billable again. Absence or a changed input subset never means deletion. Concurrent runs may duplicate checks and charges; serialize your payment batches.

Pricing uses only two platform built-ins: **$0.00005 per Actor start memory unit** (one unit through 1 GB) and **$0.002 per complete stored unique NIP/account/date receipt**, including `NIE` and unchanged repeat checks. One complete pair at 256 MB has event fees of $0.00205; 30 have $0.06005. No charge per invoice reference, request, retry or hash change. Errors, partial receipts, not-found and unsupported subjects go only to free `SUMMARY`; the start fee still applies. Platform settings determine the actual invoice.

`SUMMARY` contains running/final status, started/finished timestamps, requested/valid/unique/delivered counts, observed charged count (nullable), source attempt and byte counters, stop reason, raw Retry-After and deferred time, and per-input outcomes with available official IDs and sanitized diagnostics. Statuses include `delivered`, `invalid_input`, `not_found`, `unsupported_subject_scope`, `partial`, `error`, `not_attempted_cap`, `not_attempted_source_stop` and `delivery_uncertain`. Run status is `complete`, `partial`, `failed` or `capped`. All original indexes remain visible after a stop. An abrupt kill can leave the last checkpoint incomplete; `countersMayBeIncomplete` flags recovery from an interrupted run.

`OUTPUT` is a free KV manifest pointing to `SUMMARY` and the default dataset, with final status and delivered count. Cloud storage transport retries are disabled so failed push acknowledgments are reconciled by readback.

The free `DELIVERY` ledger stores at most 30 pending/delivered normalized receipts for same-run recovery. Exact row readback of the listed dataset items confirms delivery, including a stored row with zero charges; the dataset's item count is never trusted, because on the platform it lags a push by seconds. Restart recovery reconciles existing rows before any possible pending push; it never refetches the source. A crash during source work ends further source processing on recovery. Recovery derives the run status again from the reconciled outcomes; a pending receipt confirmed absent that cannot be re-stored within the budget or deadline is reported as `not_attempted_cap` with `spending_cap` or `deadline`. `OUTPUT` is written after `DELIVERY` and `SUMMARY`, so it never claims a status they failed to persist. Invalid state or failed storage updates fail the run and preserve stored rows. There is no cross-run cache, watch baseline, continuation cursor or exactly-once guarantee across runs. Retry unresolved entries as a fresh input, reviewing the dataset first if delivery was uncertain.

Runtime uses only `https://wykazpodatnikowvat.mf.gov.pl:443`, via anonymous HTTPS GET, no credentials, cookies, browser or proxy. No legacy-host failover. At most one redirect is permitted and must retain the same origin, route, identifiers and date. Work stops immediately on 403, 429, HTML/challenge or unexpected rejection. Retry-After is reported without a same-run 403/429 retry. Transient failures get at most two retries with 2 s then 5 s backoff plus pacing; three exhausted transient failures stop the host.

The published source limits are 100 search requests/day and 5,000 check subjects/day; a block can affect both methods until midnight. Shared-egress enforcement scope and reset timezone are undocumented. A small run can be blocked by earlier shared-IP activity. This single-subject implementation uses at most 60 initial calls for 30 unique suppliers, bounded to 66 total attempts (33 per method), including retries/redirects. Do not assume high-volume daily capacity or rotate egress to bypass a block.

Additional per-run ceilings are 180 seconds work plus up to 10 seconds cleanup, 15 seconds per HTTP attempt, 512 KiB per decoded response, 8 MiB cumulative response bytes, 2 MiB application storage payload traffic, 100 KV reads/writes, 30 dataset writes and 100 dataset reads. Cleanup is reserved before starting more work; repeated checkpoints consume real serialized bytes. Storage ceilings or deadlines can stop before 30 rows. SDK-owned bookkeeping and platform billing/transport overhead require separate platform measurement. No discovery, batch endpoints, persistent monitoring, PDFs, email/webhooks or tax certification.

`TAK`/`NIE` does not establish ownership in all contexts, payment execution, payment legality or tax protection. Retain results according to your organization's requirements and consult your own advisers. You control any invoice references and personal data you submit; use references that contain only what you need. Your supplied account is intentionally visible in your private exported receipt. This actor omits unnecessary public personal fields; no exhaustive legal clearance is claimed.

Source: [Ministry API documentation](https://www.gov.pl/web/kas/api-wykazu-podatnikow-vat) and [official FAQ](https://www.gov.pl/web/kas/pytania-i-odpowiedzi). The new host replaced the old default in October 2026. Availability, quota capacity and account assignment may change.

# Actor input Schema

## `payments` (type: `array`):

1–30 supplied payments. Dates default once at run start to Europe/Warsaw today. Individual invalid entries receive free diagnostics. NIP and account must be strings with valid checksums.

## `maxResults` (type: `integer`):

Caps stored unique NIP/account/date receipts; duplicate invoice references do not add charges.

## `requestIntervalMs` (type: `integer`):

Accepted 1200–5000 ms; runtime uses at least 2000 ms for conservative source pacing. Deadline may cap larger batches.

## Actor input object example

```json
{
  "payments": [
    {
      "invoiceReference": "DEMO-INVOICE-001",
      "nip": "7740001454",
      "bankAccount": "PL30102010260000140203550589"
    }
  ],
  "maxResults": 30,
  "requestIntervalMs": 1200
}
```

# Actor output Schema

## `rows` (type: `string`):

No description

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

No description

## `output` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("thatmike1/pl-vat-payment-proof").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("thatmike1/pl-vat-payment-proof").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 '{}' |
apify call thatmike1/pl-vat-payment-proof --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thatmike1/pl-vat-payment-proof"
        }
    }
}
```

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/JFCPI0rAy6n0GZcVe/builds/i7OSbCVR5rHxhTNXf/openapi.json
