<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bartosz Kuć</title>
    <description>The latest articles on DEV Community by Bartosz Kuć (@bartoszkuc).</description>
    <link>https://dev.to/bartoszkuc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4090240%2Fff85ca6a-70e6-4f61-97cb-9bccfa369238.jpg</url>
      <title>DEV Community: Bartosz Kuć</title>
      <link>https://dev.to/bartoszkuc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bartoszkuc"/>
    <language>en</language>
    <item>
      <title>I built a machine-readable catalog of 92 official government APIs for AI agents</title>
      <dc:creator>Bartosz Kuć</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:17:08 +0000</pubDate>
      <link>https://dev.to/bartoszkuc/i-built-a-machine-readable-catalog-of-92-official-government-apis-for-ai-agents-3518</link>
      <guid>https://dev.to/bartoszkuc/i-built-a-machine-readable-catalog-of-92-official-government-apis-for-ai-agents-3518</guid>
      <description>&lt;p&gt;If you have ever pointed an AI agent at "public data", you know the hard part is not calling the API. It is finding the right official one. Which agency publishes company records in Denmark? Does Poland's VAT register have a real endpoint or only a web form? Is there an API behind a statistics office, or just PDFs? Agents burn their first steps guessing, and they often end up at a paid reseller instead of the government source.&lt;/p&gt;

&lt;p&gt;So I built a catalog for exactly that step: &lt;a href="https://otwarteapi.pl/en/" rel="noopener noreferrer"&gt;otwarteAPI.pl&lt;/a&gt;, an open index of official public and government APIs that an agent can read directly.&lt;/p&gt;

&lt;p&gt;Disclosure up front: it is my own project. It is free, there is no login and no tracking, and it does not proxy or resell anyone's data. Every entry points straight at the official source.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is in it
&lt;/h2&gt;

&lt;p&gt;Right now it lists 92 APIs across 40 jurisdictions: 38 countries and territories, plus EU institutions and international bodies. Company registers, VAT and tax lookups, statistics offices, central banks and open data portals. A few examples: Poland's VAT white list, KRS and CEIDG, the UK's Companies House, Denmark's CVR, Norway's Brønnøysund register, France's Sirene, SEC EDGAR, FRED, Eurostat, the ECB data warehouse, GLEIF, the World Bank, and the national data portals of Singapore, India and Australia.&lt;/p&gt;

&lt;p&gt;69 of them need no key at all. Each entry names the publisher (a ministry, a registrar, a statistics office, a central bank), gives the base URL, says whether you need a key, and lists a few example questions it can answer. Everything is in English and Polish, and 38 entries have a test button on their page that calls the official API straight from your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that matters for agents
&lt;/h2&gt;

&lt;p&gt;The whole catalog is one machine-readable file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://otwarteapi.pl/.well-known/ai-catalog.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses the &lt;code&gt;ai-catalog.json&lt;/code&gt; format from the &lt;a href="https://agenticresourcediscovery.org/" rel="noopener noreferrer"&gt;Agentic Resource Discovery (ARD)&lt;/a&gt; spec, which a working group with people from Microsoft, Google and Hugging Face is developing. The same file drives the search on the site, so the page a human reads and the data an agent reads can't drift apart. There is also an &lt;a href="https://otwarteapi.pl/llms.txt" rel="noopener noreferrer"&gt;llms.txt&lt;/a&gt;, and JSON-LD on every page for crawlers that don't speak ARD yet.&lt;/p&gt;

&lt;p&gt;Every entry has a stable identifier (a URN), the URL, a description, tags and a jurisdiction code (an ISO country code, &lt;code&gt;EU&lt;/code&gt; for Union institutions, &lt;code&gt;INT&lt;/code&gt; for international bodies), so an agent can filter by country or topic before it makes a single call.&lt;/p&gt;

&lt;p&gt;If your client speaks MCP, there is also a remote MCP server at &lt;code&gt;https://otwarteapi.pl/mcp&lt;/code&gt; with one tool that searches the catalog. It is listed in the official MCP registry as &lt;code&gt;io.github.bartosz-kuc/otwarteapi&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How you would use it
&lt;/h2&gt;

&lt;p&gt;Say your agent has to check a company somewhere in Europe. Instead of hardcoding one country's endpoint, it reads the catalog, filters by jurisdiction and the company register tag, and gets the official base URL for that country. One lookup, then a direct call to the government source. No scraping, no guessing, no middleman.&lt;/p&gt;

&lt;h2&gt;
  
  
  It is open
&lt;/h2&gt;

&lt;p&gt;The catalog data is mirrored to a public repo, &lt;a href="https://github.com/bartosz-kuc/otwarteapi-catalog" rel="noopener noreferrer"&gt;bartosz-kuc/otwarteapi-catalog&lt;/a&gt;. Issues and pull requests are welcome there: a missing official API from your country, a base URL that moved, a key requirement that changed. I review the changes and fold them back into the site.&lt;/p&gt;

&lt;p&gt;If you build agents that touch public data, I would really like to hear which registers or countries you wish were in there.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>opendata</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I packaged Polish company verification as a Claude Skill</title>
      <dc:creator>Bartosz Kuć</dc:creator>
      <pubDate>Mon, 24 Aug 2026 10:32:32 +0000</pubDate>
      <link>https://dev.to/bartoszkuc/i-packaged-polish-company-verification-as-a-claude-skill-47im</link>
      <guid>https://dev.to/bartoszkuc/i-packaged-polish-company-verification-as-a-claude-skill-47im</guid>
      <description>&lt;p&gt;If you use Claude Code or the Claude apps and you ever deal with Polish companies, here is a small thing that saves a surprising amount of time: a Skill that lets Claude verify a company by its tax ID, check whether it is a registered VAT payer, look up its bank account on the government white list, pull its court-register data, and validate an EU VAT number. No API key, no signup, nothing to run beyond ordinary HTTP.&lt;/p&gt;

&lt;p&gt;I published it as an open Agent Skill. This post is how it works and how to install it.&lt;/p&gt;

&lt;p&gt;Full disclosure up front: the API behind it, &lt;a href="https://skanfirmy.pl" rel="noopener noreferrer"&gt;skanfirmy.pl&lt;/a&gt;, is my own project. It is free and keyless, and I built the Skill so agents can reach it as easily as a person reaches the website.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an Agent Skill actually is
&lt;/h2&gt;

&lt;p&gt;A Skill is just a folder with a &lt;code&gt;SKILL.md&lt;/code&gt; file: a bit of YAML frontmatter (a name and a description) and a markdown body with instructions. Claude reads the description, and when a task matches, it loads the body and follows it. There is no code to execute and no dependency to install. It is closer to a well written runbook than to a plugin.&lt;/p&gt;

&lt;p&gt;That format is portable. The same &lt;code&gt;SKILL.md&lt;/code&gt; works in Claude Code, in the Claude apps, and through the Agent SDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install it
&lt;/h2&gt;

&lt;p&gt;Drop the folder into a place Claude reads skills from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/bartosz-kuc/skanfirmy-mcp

&lt;span class="c"&gt;# personal skills, all projects&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.claude/skills
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; skanfirmy-mcp/skill ~/.claude/skills/verify-polish-company
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Claude Code and you are done. The Skill loads on its own when a request matches, so you do not have to call it by name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it
&lt;/h2&gt;

&lt;p&gt;Now you can just ask in plain language:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;is NIP 5260250995 an active VAT payer, and what is on its white list?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude picks up the Skill and runs the right check. Under the hood it is a single GET:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://skanfirmy.pl/nip/5260250995?format=json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That returns the VAT status (active, exempt, or not registered), the company details from the VAT register, and the bank accounts that sit on the official white list ("Biała Lista"). Those two facts, VAT status and account match, are the ones that decide whether a Polish B2B payment is safe to deduct, so they are worth getting right.&lt;/p&gt;

&lt;p&gt;The Skill knows about the other registers too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /regon/{nip}&lt;/code&gt; returns REGON registry data from the statistics office, and it covers sole traders, who are not in the court register.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /nip/{nip}&lt;/code&gt; also folds in the KRS court record (legal form, capital, address, representation).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /vies/{country}/{number}&lt;/code&gt; validates an EU VAT number through the European Commission's VIES service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything is a plain GET that answers JSON when you add &lt;code&gt;?format=json&lt;/code&gt;. No key, no account, no daily quota.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a Skill and not just docs
&lt;/h2&gt;

&lt;p&gt;You could paste the endpoint list into a prompt every time. The Skill does three things that a one off paste does not:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It teaches Claude &lt;em&gt;when&lt;/em&gt; to reach for these checks, so it triggers on the real intent ("verify this contractor") instead of waiting to be told the URL.&lt;/li&gt;
&lt;li&gt;It picks the right endpoint. Sole trader? That is &lt;code&gt;/regon&lt;/code&gt;, because the court register does not cover them. Foreign VAT number? That is VIES. It encodes those small decisions so you do not have to.&lt;/li&gt;
&lt;li&gt;It names the government literals to key off, like the VAT status value, instead of a translated label that would break branching.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is also an MCP server at &lt;code&gt;https://skanfirmy.pl/mcp&lt;/code&gt; for agents that speak the Model Context Protocol, with the same checks as tools and the same no-key rule. The Skill points at it, but you do not need it for the REST path.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest part
&lt;/h2&gt;

&lt;p&gt;The data comes straight from official sources: the Ministry of Finance for the VAT white list, the Ministry of Justice for the court register, the statistics office (GUS) for REGON, and the European Commission for VIES. skanfirmy.pl is an independent tool, not an official government API, and it just exposes those registers in one place with one request instead of four.&lt;/p&gt;

&lt;p&gt;The Skill is MIT licensed and lives here: &lt;a href="https://github.com/bartosz-kuc/skanfirmy-mcp/tree/main/skill" rel="noopener noreferrer"&gt;github.com/bartosz-kuc/skanfirmy-mcp&lt;/a&gt;. If you wire company checks into agent workflows, I would genuinely like to hear what is missing.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>mcp</category>
      <category>poland</category>
    </item>
    <item>
      <title>Checking Polish companies from code: VAT, KRS, REGON, EU VAT (REST + Python + MCP)</title>
      <dc:creator>Bartosz Kuć</dc:creator>
      <pubDate>Sun, 23 Aug 2026 18:18:20 +0000</pubDate>
      <link>https://dev.to/bartoszkuc/checking-polish-companies-from-code-vat-krs-regon-eu-vat-rest-python-mcp-2pkc</link>
      <guid>https://dev.to/bartoszkuc/checking-polish-companies-from-code-vat-krs-regon-eu-vat-rest-python-mcp-2pkc</guid>
      <description>&lt;p&gt;If you invoice or onboard Polish companies, sooner or later you have to check two dull things that turn out to matter a lot: is this company actually a registered VAT payer, and is the bank account they gave you the one that's on the government's official white list ("Biała Lista")? Both of those affect whether you can deduct the cost and reclaim VAT, so it's not really optional.&lt;/p&gt;

&lt;p&gt;The annoying part is that the data lives in four different places: the Ministry of Finance, the KRS court register, GUS (the stats office), and the EU's VIES service. Each one has its own API and its own quirks.&lt;/p&gt;

&lt;p&gt;I got tired of gluing those together every time, so I wrapped them behind a few plain HTTP calls that return JSON. Full disclosure: &lt;a href="https://skanfirmy.pl" rel="noopener noreferrer"&gt;skanfirmy.pl&lt;/a&gt; is mine. It's free, no key, no signup, and the web layer runs client-side with no tracking. Here's how you'd actually use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  REST: one GET, one JSON
&lt;/h2&gt;

&lt;p&gt;Cheapest thing you can do is check a NIP (the tax ID):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://skanfirmy.pl/nip/5260250995
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get back the VAT status (active, exempt, or not registered), the company details from the VAT register, and the accounts sitting on the white list.&lt;/p&gt;

&lt;p&gt;The paths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /nip/{nip}&lt;/code&gt; gives VAT status + white-list data for one NIP&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /nips/{list}&lt;/code&gt; takes several NIPs at once (comma-separated)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /regon/{nip}&lt;/code&gt; returns data from the REGON register (GUS)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /vies/{country}/{number}&lt;/code&gt; validates an EU VAT number, e.g. &lt;code&gt;/vies/DE/811128135&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a plain GET that returns JSON, so it drops into anything that can make an HTTP request: a cron job, a lambda, a CI step, whatever.&lt;/p&gt;

&lt;p&gt;I wrote up the REGON/GUS endpoint on its own page, with examples in a few languages and how it compares to the GUS BIR SOAP service: &lt;a href="https://skanfirmy.pl/api-gus" rel="noopener noreferrer"&gt;Polish company data from GUS (REGON) by NIP&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;requests&lt;/code&gt; and a few lines. This one raises if the company isn't an active VAT payer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_vat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://skanfirmy.pl/nip/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vatStatus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Czynny&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# status comes back in Polish; compare against the raw value
&lt;/span&gt;        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NIP &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: VAT status = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check_vat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5260250995&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;White-list accounts:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accountNumbers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing that bit me: the status strings from the Ministry come back in Polish (&lt;code&gt;Czynny&lt;/code&gt; = active, &lt;code&gt;Zwolniony&lt;/code&gt; = exempt). Compare against the original string, and don't translate before you branch on it, or the check silently breaks the day someone flips the UI language.&lt;/p&gt;

&lt;p&gt;Got a big list to run? Use &lt;code&gt;GET /nips/{list}&lt;/code&gt;, or the &lt;a href="https://skanfirmy.pl/bulk" rel="noopener noreferrer"&gt;/bulk&lt;/a&gt; page if you just need a CSV once.&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP (for agents)
&lt;/h2&gt;

&lt;p&gt;This is the part I actually built the thing for. There's an MCP server at &lt;code&gt;https://skanfirmy.pl/mcp&lt;/code&gt; with 9 tools and no API key, so an agent (say, an accounting assistant) can run the same NIP check a human would click through.&lt;/p&gt;

&lt;p&gt;JSON-RPC 2.0 over POST. Calling a tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://skanfirmy.pl/mcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "sprawdz_nip",
      "arguments": { "nip": "5260250995" }
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tools/list&lt;/code&gt; gives you all of them with their input schemas. If your agent only speaks REST, there's an &lt;code&gt;llms.txt&lt;/code&gt; at &lt;code&gt;https://skanfirmy.pl/llms.txt&lt;/code&gt; describing the endpoints in a model-readable way. And if you need more than the Polish registers, I keep a sister catalog of public APIs aimed at agents over at &lt;a href="https://otwarteapi.pl" rel="noopener noreferrer"&gt;otwarteapi.pl&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When one check isn't enough
&lt;/h2&gt;

&lt;p&gt;VAT status and white-list accounts change, sometimes day to day, and a one-off check won't tell you when that happens. So there's &lt;a href="https://skanfirmy.pl/monitoring" rel="noopener noreferrer"&gt;/monitoring&lt;/a&gt;: it diffs daily and pings you over an HMAC-signed webhook when something moves. You verify the signature on your end and react, instead of polling the registers in a loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's basically it
&lt;/h2&gt;

&lt;p&gt;curl for a quick look, &lt;code&gt;requests&lt;/code&gt; to put it in code, MCP if an agent is doing the checking. All JSON, no signup, no key. (It's bilingual too: English pages live under &lt;code&gt;/en/&lt;/code&gt;, and the REST/MCP endpoints don't care about language either way.)&lt;/p&gt;

&lt;p&gt;If you're already solving this differently, especially the white-list account matching, I'd genuinely like to hear how. That part is fiddlier than it looks.&lt;/p&gt;

</description>
      <category>poland</category>
      <category>api</category>
      <category>mcp</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
