Poland VAT Whitelist Checker & Supplier Monitor
Pricing
$5.00 / 1,000 resolved supplier checks
Poland VAT Whitelist Checker & Supplier Monitor
Bulk-check up to 3,000 Polish suppliers against the official VAT White List (Biała Lista): verify VAT status and registered bank accounts, preserve official request IDs, and monitor deterministic supplier changes between scheduled runs. Failed checks never become false absences.
Pricing
$5.00 / 1,000 resolved supplier checks
Rating
0.0
(0)
Developer
Vadim Bezrukov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 hours ago
Last modified
Categories
Share
Check VAT status and registered bank accounts today, then run the same supplier portfolio again to receive deterministic, webhook-ready change events.
Unofficial community Actor. This Actor is not affiliated with, sponsored by, or endorsed by the Polish Ministry of Finance (MF) or National Revenue Administration (KAS). It reads their public VAT White List API.
Bulk-check a Polish supplier portfolio against the official Ministry of Finance VAT White List (Biała Lista), verify an optional NIP + bank-account pair, and monitor deterministic VAT or registered-account changes between runs.
The Actor is built for accounting, AP, procurement, ERP and supplier-compliance workflows. It uses the official JSON API over direct HTTP: no browser, CAPTCHA, login, proxy, proxy rotation, VIES, KRS/CEIDG enrichment or private database.
This is not tax or legal advice. The Actor reports what the official register returned for the requested date and does not decide whether a payment is lawful or recommend a tax procedure.
Use from AI agents with MCP
Connect the public Actor directly at
https://mcp.apify.com?tools=automa-flow/poland-vat-whitelist-monitor. Ask your
agent to verify a supplier or bank account and preserve the official request ID,
requested date, and explicit per-item status in its answer.
What you can do
- Bulk Polish VAT supplier verification — reconcile up to 3,000 NIPs in a single run with one explicit output row per input.
- Supplier master-data monitoring — reuse a
monitorIdand retain only the last verified normalized state in Apify KVS. - Weekly VAT-status change detection — receive exact
vat_status_changedand registration-state/date events. - Bank-account change monitoring — compare sorted account hashes and emit
bank_account_added/bank_account_removedwithout keeping raw accounts in monitor state. - Pre-payment verification — include
bankAccountto run the official NIP + accountTAK/NIEmethod and retain both official request IDs.
Why use the supplier monitor instead of a one-off checker?
The default Dataset always keeps one explicit reconciliation row per input, so
AP and supplier-master workflows can join results without guessing which NIP was
lost. In monitor mode, only successful official observations advance state;
source failures stay visible and cannot manufacture a VAT/account change. The
changes view is already flattened for scheduled-run webhooks.
Input
{"records": [{"nip": "PL 526-025-02-74","reference": "invoice-2026-0042","bankAccount": "PL73 1111 1111 1111 1111 1111 1111"}],"mode": "monitor","monitorId": "weekly-ap-watchlist","onlyChanges": false,"includeFullBankAccounts": false}
recordsis required and accepts 1–3,000 rows.nipis normalized from PL/spaces/dashes and must pass the Polish checksum.referenceis optional, at most 128 characters, and is echoed unchanged.bankAccountis optional Polish NRB/PL IBAN. It is checksum-validated before any request and is never logged or included in an error URL.modedefaults tosnapshot.monitorrequires a safe, stablemonitorId.asOfDatedefaults to the current Europe/Warsaw date. The official register currently permits dates in the current year and the five preceding calendar years.onlyChanges=trueminimizes unchanged profile details, but deliberately keeps one explicit status row per input so batch reconciliation cannot silently lose suppliers. Use thechangesDataset view for event-only webhooks.includeFullBankAccountsdefaults to false. Enable it only when the workflow truly needs full registered accounts.
Concurrency, retries, delays and proxy internals are intentionally not public inputs. Official quotas, rather than CPU, are the limiting resource.
Output and failure semantics
Each input row produces one row with:
- stable
source, normalizedsource_id,source_url, UTCscraped_at,schema_versionand semanticfingerprint; SUCCESS,NOT_FOUND,PARTIAL,FAILEDorINVALID_INPUT;- normalized
ACTIVE,EXEMPT,NOT_REGISTEREDorUNKNOWNVAT status; - masked registered accounts and deterministic account hashes;
- optional authoritative
account_checkwith last four digits only; - the Ministry search request ID and optional account-check request ID;
changed,change_typeand deterministicchanges[]in monitor mode;- a safe structured
erroron unverified work.
NOT_FOUND is only produced after HTTP 200 with a valid response entry and an
empty subjects array. Timeout, HTTP 408/429/5xx, quota exhaustion, nightly
maintenance, malformed HTTP-200 JSON/schema and account-check failure are never
converted to absence. A failed supplier does not terminate valid siblings.
The run itself fails, after publishing explicit rows, only when the whole run is untrustworthy: every official search batch failed, the official allowance prevented every check, the HTTP-200 response envelope materially changed, or a billing limit changed while publishing.
A partial outcome succeeds instead. If the official allowance stops some checks
after others resolved, the run succeeds, the unattempted suppliers carry
explicit SOURCE_QUOTA rows, and the status message names how many were
stopped. This keeps the ACTOR.RUN.SUCCEEDED webhook firing for scheduled
monitors, so a cycle that did contain verified changes is never skipped
silently. Filter status in the diagnostics view to see what was missed.
One supplier the parser cannot read, such as an unrecognized VAT status or a
checksum-invalid registered account, is an isolated MALFORMED_SUBJECT row for
that supplier only. It does not fail the run and does not stop the remaining
suppliers from being checked.
Monitoring
State is namespaced by monitorId + normalized NIP in an Apify named KVS. It
contains only the last verified semantic observation, its fingerprint and
account hashes. Raw source payloads and full bank accounts are never retained.
The first verified monitor run is a baseline (changed=false). Later verified
runs can emit:
vat_status_changedregistration_state_changedregistration_date_changedremoval_date_changedrestoration_date_changedbank_account_addedbank_account_removed- supplier name, REGON or KRS changes already present in the official response
A failed profile never overwrites good state. If the supplier profile succeeds
but its requested account check fails, the row is PARTIAL; the independently
verified profile can advance the VAT/account-set baseline because the failed
field is not part of that baseline.
Official source limits and update window
The current official production documentation is API v1.6: https://www.gov.pl/web/kas/api-wykazu-podatnikow-vat
search: 100 requests/day, at most 30 subjects/request — a practical maximum of approximately 3,000 searched NIPs/day.check: 5,000 subjects/day.- Exhausting either allowance can block both API methods and the public search until 00:00. The Actor stops remaining work and never changes egress identity to multiply that allowance.
- A retry spends one request from the same 100/day search allowance, so the
Actor sizes its retry budget from what the allowance can still fund. At the
3,000-supplier maximum all 100 requests are committed to first attempts and
the run performs no retries: a transient upstream failure then costs that one
batch of 30 an explicit
FAILEDrow instead of consuming the allowance a later batch still needs. Below roughly 2,700 suppliers there is real retry headroom. - The register is updated once on working days. The Ministry warns of possible disruption during 22:00–00:00 Europe/Warsaw, so retries are suppressed in that window.
- The official daily flat file is the documented option for substantially larger verification volumes; it is outside this MVP.
Because allowances can be enforced by egress IP, a representative 300-NIP direct-HTTP run from Apify is a pre-publication gate. It was run on 2026-09-03: 300 suppliers over 10 search batches resolved with a 100% useful-output rate, no HTTP 429, no quota collision and one transient retry, using shared Apify egress without a browser, CAPTCHA, login or proxy. A single run still consumes its share of the official 100-request daily search allowance, and a retry consumes one more, so schedule large portfolios accordingly.
Privacy
The Ministry response can include PESEL-capable fields, representatives, authorized clerks, partners and personal addresses. The parser uses an explicit allowlist and never returns or stores those fields. It also never stores raw responses. Registered accounts are masked by default; monitor state uses only SHA-256 values. The full-account output is an explicit opt-in and full accounts never appear in logs.
Pay-per-event pricing
One supplier_checked event at $0.005 per resolved supplier ($5 per 1,000),
with platform usage included and no separate start fee. A supplier can generate
at most one event, even when an extra official account request is needed.
Billable: complete SUCCESS and authoritative NOT_FOUND rows, including a
supplier that monitor mode reports as unchanged. A scheduled monitor run
therefore costs the same per supplier as the first run; onlyChanges reduces
row size, not price.
Free: invalid input, retries, PARTIAL, FAILED, quota/source failures,
billing-limit skips and KVS operations.
| Resolved suppliers | Actor charge |
|---|---|
| 100 | $0.50 |
| 1,000 | $5.00 |
| 3,000 | $15.00 |
Set maxTotalChargeUsd on a run or Task to cap spend. Suppliers that the cap
cannot cover are never contacted and are published as explicit
MAX_TOTAL_CHARGE_REACHED rows, so a capped run still reconciles one row per
input and never advances monitor state for work it did not pay for.
Run through the Apify API
Keep the API token in an environment secret; never paste it into Actor input or source control.
curl -X POST \"https://api.apify.com/v2/acts/<ACTOR_ID>/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"records": [{"nip": "5260250274", "reference": "supplier-001"}],"mode": "snapshot"}'
Schedule and webhook example
Create an Apify Task with a stable monitor input, then schedule it weekly after the nightly source window, for example every Monday at 06:00 Europe/Warsaw:
{"records": [{"nip": "5260250274", "reference": "supplier-001"},{"nip": "7000000009", "reference": "supplier-002"}],"mode": "monitor","monitorId": "weekly-ap-watchlist","onlyChanges": true}
Subscribe a webhook to the Task's ACTOR.RUN.SUCCEEDED event. From the webhook
payload's default Dataset ID, fetch the flattened event view:
GET https://api.apify.com/v2/datasets/<DATASET_ID>/items?view=changes&clean=true
The view is empty when there are no deterministic changes. Failure/status rows
remain available in the default Dataset. The diagnostics view projects status
and error columns for every row; filter status client-side when selecting only
failures.
Local verification
Offline fixture demonstration:
$uv run python actors/poland-vat-whitelist-monitor/scripts/local_run.py
Manual direct-source smoke (not used by CI):
$uv run python actors/poland-vat-whitelist-monitor/scripts/smoke_test.py 5260250274
Full repository gate:
uv run pytestuv run ruff check .uv run ruff format --check .uv run mypy
The dated source evidence, legal/privacy review, pending hosted gate and economic
guardrail are recorded in experiments/poland-vat-whitelist/README.md.