Cross-Border Credit Risk: Screen Companies Across Poland + Austria in 2 API Calls
Central Europe is a single economic zone in everything except the paperwork. A German manufacturer sources from Polish suppliers. An Austrian logistics firm contracts with Czech and Polish carriers. A Warsaw-based factoring company finances invoices for Austrian SMEs. Money moves across borders daily - but the tools for checking who you're doing business with are still stuck inside national silos.
If you're vetting a company that operates in both Poland and Austria, you need two sets of insolvency registries. Do it manually and you're clicking through government portals in two languages, cross-referencing names across different legal entity identifiers. Do it with enterprise credit bureaus and you're looking at a subscription that costs more than the deal you're evaluating.
Here's a lighter-weight alternative: a two-call API pipeline that checks the official public insolvency registries of both countries and returns a single credit decision.
The Two Registries
Poland's debtor registry covers bankruptcy proceedings (upadlosc), restructuring proceedings (restrukturyzacja), and enforcement actions. It has nine search modes: you can look up companies by tax ID, individuals by name, cases by court signature, or search for entities tied to specific shareholders, assets, or advisors. It's the central source for insolvency intelligence on Polish counterparties.
Austria's insolvency publications cover three proceeding types: Konkursverfahren (bankruptcy), Sanierungsverfahren (reorganization with a restructuring plan), and Schuldenregulierungsverfahren (debt settlement for individuals). Each entry includes the debtor name, case number, court, appointed administrator, filing deadlines, and creditor meeting dates.
Neither registry has a public API. Both are accessible programmatically through Apify actors that parse the public web interfaces into structured JSON.
The Pipeline: 2 Calls, 1 Decision
The idea is straightforward. Given a company name and tax identifier:
- Call 1 - Poland: Search the debtor registry by company name and NIP. If the company has active insolvency or restructuring proceedings, flag it immediately.
- Call 2 - Austria: Search the insolvency publications by company name. Cross-reference against the Polish result. If proceedings exist in either country, flag.
Here's the code:
import requests
import os
import time
APIFY_TOKEN = os.environ["APIFY_TOKEN"]
# Apify actor IDs
KRZ_ACTOR = "Izh9WtW5BuFJNjuKX" # Poland debtor registry
EDIKTSDATEI_ACTOR = "YZyc5zWAzk5avOabZ" # Austria insolvency publications
HEADERS = {"Authorization": f"Bearer {APIFY_TOKEN}", "Content-Type": "application/json"}
def call_actor(actor_id: str, input_data: dict) -> dict:
"""Run an Apify actor and wait for results."""
# Start the actor run
resp = requests.post(
f"https://api.apify.com/v2/acts/regdata~{actor_id}/runs",
headers=HEADERS,
json={"input": input_data, "waitForFinish": 120}
)
resp.raise_for_status()
run_data = resp.json()
# Fetch the dataset
dataset_id = run_data["data"]["defaultDatasetId"]
items_resp = requests.get(
f"https://api.apify.com/v2/datasets/{dataset_id}/items",
headers=HEADERS
)
items_resp.raise_for_status()
return {"run": run_data, "results": items_resp.json()}
def check_poland(name: str, nip: str) -> dict:
"""Check Polish debtor registry (KRZ) for insolvency proceedings."""
result = call_actor(KRZ_ACTOR, {
"searchType": "companies",
"searchValue": nip or name,
"includeDetails": True
})
proceedings = []
for item in result["results"]:
if not item.get("error"):
proceedings.append({
"debtor": item.get("debtorName", name),
"caseSignature": item.get("caseSignature", ""),
"proceedingType": item.get("proceedingType", ""),
"court": item.get("court", ""),
"status": item.get("status", "ACTIVE"),
})
return {
"country": "PL",
"registry": "KRZ",
"totalResults": len(result["results"]),
"activeProceedings": proceedings,
"flagged": len(proceedings) > 0,
}
def check_austria(name: str) -> dict:
"""Check Austrian insolvency publications (Ediktsdatei)."""
result = call_actor(EDIKTSDATEI_ACTOR, {
"searchQuery": name,
"searchType": "all",
"includeDetails": True
})
proceedings = []
for item in result["results"]:
if not item.get("error"):
proceedings.append({
"debtor": item.get("debtorName", name),
"caseNumber": item.get("caseNumber", ""),
"proceedingType": item.get("proceedingType", ""),
"court": item.get("court", ""),
"administrator": item.get("administrator", ""),
})
return {
"country": "AT",
"registry": "Ediktsdatei",
"totalResults": len(result["results"]),
"activeProceedings": proceedings,
"flagged": len(proceedings) > 0,
}
def credit_decision(pl: dict, at: dict) -> dict:
"""Generate a credit decision from the two registry checks.
Returns one of: CLEAN, REVIEW, DECLINE
"""
signals = []
if pl["flagged"]:
signals.append(f"PL: {len(pl['activeProceedings'])} active proceeding(s) in KRZ")
if at["flagged"]:
signals.append(f"AT: {len(at['activeProceedings'])} active proceeding(s) in Ediktsdatei")
if len(signals) >= 2:
decision = "DECLINE"
elif len(signals) == 1:
decision = "REVIEW"
else:
decision = "CLEAN"
return {
"decision": decision,
"signals": signals,
"rationale": _rationale(decision, signals),
"poland": pl,
"austria": at,
}
def _rationale(decision: str, signals: list[str]) -> str:
if decision == "CLEAN":
return "No insolvency proceedings found in Poland or Austria."
if decision == "REVIEW":
return f"Insolvency flag in one jurisdiction. {signals[0]}. Review before proceeding."
return (
f"Active proceedings in both jurisdictions: {'; '.join(signals)}. "
"Decline or require full risk assessment before proceeding."
)
# Example usage
if __name__ == "__main__":
company = {"name": "Alpine Bau GmbH", "nip": "525-000-00-01"}
print(f"Screening: {company['name']}\n")
pl_result = check_poland(company["name"], company["nip"])
at_result = check_austria(company["name"])
decision = credit_decision(pl_result, at_result)
print(f"Decision: {decision['decision']}")
print(f"Rationale: {decision['rationale']}")
if decision["signals"]:
for s in decision["signals"]:
print(f" - {s}")
Making It a Recurring Watchlist
A one-time check is useful for onboarding. A recurring check is where this becomes a credit risk system. Wrap the pipeline in a scheduled job that runs weekly against your counterparty list:
import json
from datetime import datetime
def monitor_portfolio(companies: list[dict]):
"""Run the cross-border pipeline against a list of companies."""
report = {
"timestamp": datetime.utcnow().isoformat(),
"total": len(companies),
"decisions": {"CLEAN": 0, "REVIEW": 0, "DECLINE": 0},
"alerts": [],
}
for company in companies:
pl = check_poland(company["name"], company.get("nip", ""))
at = check_austria(company["name"])
decision = credit_decision(pl, at)
report["decisions"][decision["decision"]] += 1
if decision["decision"] in ("REVIEW", "DECLINE"):
report["alerts"].append({
"company": company["name"],
"decision": decision["decision"],
"signals": decision["signals"],
"rationale": decision["rationale"],
})
return report
For ongoing monitoring, you'd run this weekly and diff against previous runs. A company that was CLEAN last week and REVIEW this week is your signal to pick up the phone.
This is the inspection-first pattern: fresh registry data on a schedule, alerts when the picture changes, same pipeline every time so the process is repeatable and auditable.
Why This Beats Manual Checks
A credit analyst checking both registries manually for 100 counterparties would need to:
- Navigate two separate government portals in two languages
- Cross-reference company names across different tax ID systems
- Copy-paste results into a spreadsheet
- Remember to repeat the check next month
The pipeline above does the same thing in under a minute per company - and you never forget to re-check. The marginal cost is a few cents per lookup, pay-per-use with no subscription.
For teams building this into a production workflow, the getregdata GitHub repo ships packaged agent skills that wrap these actors into repeatable prompts. The regdata-credit-risk skill bundles the Poland and Austria checks into a single credit assessment framework with early-warning indicators and decision logic already built in. Install it, point it at your counterparty list, and you have a recurring watchlist.
The Companion Piece: KYC Onboarding
This credit risk pipeline has a sibling. Last week we published a KYC onboarding workflow that screens Polish companies for beneficial owners, regulatory flags, and insolvency risk in three API calls. That pipeline answers "who am I doing business with?" This pipeline answers "should I keep doing business with them?" Together they cover the full counterparty lifecycle: onboard, then monitor.
Going Pan-European
Two countries is a start. The same pattern extends:
- Spain: The corporate gazette (BORME) publishes daily dissolution and insolvency acts. Parse structured JSON from official publications to catch Spanish counterparties entering insolvency.
- France: Aggregated company data with director networks and simplified financials can surface distress signals before they hit the official registries.
Each additional country is one more API call in the pipeline, one more signal feeding the decision function. The architecture stays the same.
Getting Started
Both actors are available on Apify with a free tier that covers testing:
- Poland KRZ Debtor Registry - $0.025 per result (free tier available)
- Austria Ediktsdatei Insolvency - $0.005 per result (free tier available)
Clone the pipeline code above, drop in your Apify API token, and run a test against a handful of counterparties. You'll have cross-border credit signals in production before lunch.
Cross-border credit risk shouldn't require cross-border credit bureau subscriptions. Two API calls, one decision - that's the pattern.
Top comments (0)