<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://apievangelist.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://apievangelist.com/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-06-15T12:12:45+00:00</updated><id>https://apievangelist.com/feed.xml</id><title type="html">API Evangelist</title><subtitle>Understanding the technology, business, policies, and people of Apis.</subtitle><author><name>Kin Lane</name></author><entry><title type="html">The Architecture Behind 10,000 API Providers</title><link href="https://apievangelist.com/2026/06/14/the-architecture-behind-10000-api-providers/" rel="alternate" type="text/html" title="The Architecture Behind 10,000 API Providers" /><published>2026-06-14T00:00:00+00:00</published><updated>2026-06-14T00:00:00+00:00</updated><id>https://apievangelist.com/2026/06/14/the-architecture-behind-10000-api-providers</id><content type="html" xml:base="https://apievangelist.com/2026/06/14/the-architecture-behind-10000-api-providers/"><![CDATA[<p>When I started API Evangelist in September 2010, I was writing stories from a one-bedroom apartment in Eugene, Oregon, trying to make sense of what Twitter, Twilio, and Stripe were doing to software development. I had no idea it would eventually turn into a catalog of 10,000 API providers indexed across a searchable network. But here we are.</p>

<p>The <a href="https://github.com/api-evangelist">API Evangelist GitHub organization</a> just crossed 10,000 repositories. Each one represents a single API provider — from AWS and Salesforce to federal government agencies, DeFi protocols, academic databases, university library catalogs, and niche vertical tools that most people have never heard of. The question I keep getting asked is: how does a GitHub organization of 10,000 repos become a navigable API network? The answer is an architecture that took me about twelve years to figure out, and it hinges on three things working together — a standard, a catalog, and a set of tooling that treats the standard seriously.</p>

<h2 id="every-repo-is-a-machine-readable-provider-profile">Every Repo Is a Machine-Readable Provider Profile</h2>

<p>The unit of the catalog is a GitHub repository named after the provider. Inside every repo, at the root, is an <code class="language-plaintext highlighter-rouge">apis.yml</code> file in the <a href="https://apisjson.org">APIs.json</a> format (currently v0.19). That file is the source of truth for everything I know about that provider.</p>

<p>It declares the provider’s identity: an <code class="language-plaintext highlighter-rouge">aid</code> (a stable, machine-readable identifier), a human name, a description, a set of tags, and a <code class="language-plaintext highlighter-rouge">humanURL</code> — the front door. It then lists specific API entries, each with its own properties pointing to machine-readable artifacts: OpenAPI specs, AsyncAPI specs, JSON Schemas. And it carries common properties that cut across all the APIs a provider offers — links to their Plans page, Rate Limits documentation, FinOps pricing data, a JSONLDContext for their vocabulary, and a Blog feed.</p>

<p>The result across 10,000 repos is: 10,754 OpenAPI specs discovered and indexed, 14,123 unique tags, and property coverage that tells me a lot about where the industry has and hasn’t invested. Website coverage across the catalog is 7,836 providers. Documentation coverage is 6,723. Plans coverage is 2,116 — meaning roughly 21% of providers have bothered to publish machine-readable pricing. Rate Limits coverage is 2,295. FinOps is 2,016. Those gaps are as interesting to me as the numbers themselves.</p>

<h2 id="apisjson-is-the-vocabulary-that-makes-it-parseable">APIs.json Is the Vocabulary That Makes It Parseable</h2>

<p>The reason any of this works at scale is that <a href="https://apisjson.org">APIs.json</a> is a standard with a defined vocabulary. The property types — <code class="language-plaintext highlighter-rouge">OpenAPI</code>, <code class="language-plaintext highlighter-rouge">AsyncAPI</code>, <code class="language-plaintext highlighter-rouge">JSONSchema</code>, <code class="language-plaintext highlighter-rouge">Plans</code>, <code class="language-plaintext highlighter-rouge">RateLimits</code>, <code class="language-plaintext highlighter-rouge">FinOps</code>, <code class="language-plaintext highlighter-rouge">Vocabulary</code>, <code class="language-plaintext highlighter-rouge">JSONLDContext</code>, <code class="language-plaintext highlighter-rouge">Blog</code> — are not labels I invented for my own crawler. They are standardized terms maintained by <a href="https://apicommons.org">API Commons</a> that any tooling can parse without custom logic per provider.</p>

<p>This is the part that most people underestimate when they think about API discovery at scale. The problem is not scraping. I can scrape. The problem is that scraped data has no shared schema, so every consumer has to write a custom parser for every provider. APIs.json solves that by giving every provider the same vocabulary for describing what they publish. When my tooling sees <code class="language-plaintext highlighter-rouge">type: OpenAPI</code> in an <code class="language-plaintext highlighter-rouge">apis.yml</code>, it knows exactly what to do with that URL — regardless of whether the provider is a two-person startup or a Fortune 500 company.</p>

<p>I started working on APIs.json in 2014 alongside Steve Willmott and others in the community. The goal was always to create a discovery primitive that sat one layer above the API specs themselves — not a replacement for OpenAPI, but an index of where OpenAPI (and everything else) lives. Twelve years later, with 10,000 repos all carrying an <code class="language-plaintext highlighter-rouge">apis.yml</code>, I feel like that bet paid off.</p>

<h2 id="the-standards-layer-is-the-governance-layer">The Standards Layer Is the Governance Layer</h2>

<p>One thing that took me longer to articulate is that the catalog is not just a discovery artifact — it is also a governance artifact. When I add a JSONSchema property to a provider’s <code class="language-plaintext highlighter-rouge">apis.yml</code>, I am capturing their data model in a machine-readable format that any downstream consumer can validate against. When I add a Vocabulary property, I am anchoring their domain terms. When I add a JSONLDContext, I am connecting their data structures to the linked data web.</p>

<p>These are not decorative. The Standards layer of the catalog — the combination of JSONSchema, Vocabulary, JSONLDContext, and Plans/RateLimits/FinOps — gives me the raw material for governance tooling. I can ask questions like: which providers in the Healthcare tag have published a JSONSchema for their data models? Which providers in the Financial Services category have machine-readable pricing? Which government agencies have a Vocabulary that other agencies could reuse? The <code class="language-plaintext highlighter-rouge">apis.yml</code> in each repo is the hook I use to answer those questions programmatically, across 10,000 providers, without manual lookups.</p>

<p>This is why I put so much energy into the property coverage numbers. Every gap in the coverage map is a place where the industry has not yet invested in making itself legible to machines. The 78% of providers without machine-readable Plans are not bad actors — they just haven’t been asked to publish that data in a format tooling can consume. The catalog makes the ask visible.</p>

<h2 id="how-it-feeds-apisio">How It Feeds APIs.io</h2>

<p>The GitHub repos don’t just sit there. They feed <a href="https://apis.io">APIs.io</a>, the search and discovery layer I maintain on top of the catalog. The crawler reads every <code class="language-plaintext highlighter-rouge">apis.yml</code>, indexes the provider identity, the API entries, and the properties, and surfaces them through a search interface organized around <a href="https://tags.apis.io/">14,123 unique tags</a>.</p>

<p>That tag vocabulary is one of the most useful artifacts to come out of the catalog work. Tags in <code class="language-plaintext highlighter-rouge">apis.yml</code> files are freeform — providers contribute their own terms — but over 10,000 repos, patterns emerge. The top tags tell me which categories of the API economy are most active. The long tail tells me where the catalog still has gaps. And because tags are indexed and browsable at <a href="https://tags.apis.io/">tags.apis.io</a>, they give both humans and agents a structured entry point into the network without needing to know what specific provider they’re looking for.</p>

<p>The result is that what started as a personal blog about the API economy has become infrastructure. The blog is still there — this post is part of it — but underneath it is a machine-readable catalog of the providers I’ve been writing about for sixteen years. The stories and the structured data are built on the same foundation, which is exactly how I wanted it to work when I started sketching this out in 2014.</p>

<h2 id="why-github-as-the-storage-layer">Why GitHub as the Storage Layer</h2>

<p>Using GitHub as the backbone of the catalog was a practical decision that turned out to have real structural benefits. Git gives me version history on every <code class="language-plaintext highlighter-rouge">apis.yml</code> — I can see when a provider added Plans coverage, when their OpenAPI URL changed, when they picked up a new tag. GitHub’s API gives me programmatic access to the catalog without maintaining my own storage infrastructure. And the public nature of the organization means anyone can open a pull request to correct a provider profile, add a missing spec URL, or flag an outdated property.</p>

<p>The catalog is not a database I maintain in isolation. It is a public, version-controlled, community-editable index of the API economy, structured around an open standard. That combination — open standard, public repo, Git history — is what lets me hand it off to tooling, to agents, to other researchers, and have some confidence that they’re working from the same source of truth I am.</p>

<p>Ten thousand repos. Sixteen years of work. One <code class="language-plaintext highlighter-rouge">apis.yml</code> at a time.</p>]]></content><author><name>Kin Lane</name></author><category term="APIs.json" /><category term="API Discovery" /><category term="GitHub" /><category term="APIs.io" /><category term="Standards" /><category term="Network" /><summary type="html"><![CDATA[When I started API Evangelist in September 2010, I was writing stories from a one-bedroom apartment in Eugene, Oregon, trying to make sense of what Twitter, Twilio, and Stripe were doing to software development. I had no idea it would eventually turn into a catalog of 10,000 API providers indexed across a searchable network. But here we are.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/1939-new-york-worlds-fair-city-skyline-clouds-sun-shadows.jpeg" /><media:content medium="image" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/1939-new-york-worlds-fair-city-skyline-clouds-sun-shadows.jpeg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">API Value Exchange</title><link href="https://apievangelist.com/2026/06/12/api-value-exchange/" rel="alternate" type="text/html" title="API Value Exchange" /><published>2026-06-12T00:00:00+00:00</published><updated>2026-06-12T00:00:00+00:00</updated><id>https://apievangelist.com/2026/06/12/api-value-exchange</id><content type="html" xml:base="https://apievangelist.com/2026/06/12/api-value-exchange/"><![CDATA[<p>I have been writing about API monetization since 2011. Not consistently, but in recurring waves — whenever the business reality of APIs forces itself back to the surface. Early on I was fascinated by the mechanics: <a href="https://apievangelist.com/2014/11/08/resource-base-api-monetization-vs-experience-based-api-monetization/">resource-based versus experience-based pricing</a>, <a href="https://apievangelist.com/2015/08/29/an-api-monetization-framework-to-help-me-standardize-pricing-for-the-apis-i-bring-online/">the cost-to-value accounting framework I tried to formalize</a>, <a href="https://apievangelist.com/2015/09/14/are-there-really-any-monetization-opportunities-around-open-data-and-apis/">the uncomfortable question of whether open government data could ever generate revenue</a> without betraying its public mission. I spent a lot of time in that era trying to help government agencies — the Forest Service, the National Park Service, the Bureau of Land Management — understand that the value flowing through their APIs was real and worth naming, even if calling it “monetization” was politically untenable.</p>

<p>I feel that last part is worth thinking about more. The word monetization has always been a barrier in exactly the places where API value matters most. When I was pushing the Department of Agriculture to <a href="https://apievangelist.com/2014/10/16/i-need-help-to-make-sure-the-dept-of-agriculture-leads-with-apis-in-their-parks-and-recreation-rfp/">make APIs a first-class citizen in the Recreation One Stop RFP</a>, I couldn’t walk into those rooms talking about monetizing access to campsite reservations or national park geospatial data. The value was real — millions of families planning camping trips, small businesses building itinerary tools, agencies making operations data portable and interoperable across the Forest Service, Army Corps of Engineers, Bureau of Reclamation, and a dozen other federal partners — but the word “monetization” shut the conversation down before it started.</p>

<p>I have been using <a href="https://apievangelist.com/2017/05/11/using-public-lands-as-an-analogy-when-talking-about-public-data-apis/">public lands as an analogy for public data APIs</a> for years because of this. A national park isn’t valuable primarily because it generates revenue. It’s valuable because of what it makes possible: recreation, conservation, ecological research, local economies, a shared sense of what this country is. The value is real, diverse, and distributed across many stakeholders — not all of whom are in a financial relationship with the park service. The same is true of a well-designed public data API. Calling the question “how do we monetize this?” misframes what’s actually happening, which is an exchange of value — in many different directions, not all of them financial.</p>

<p>I want to start calling this what it is: API value exchange.</p>

<p>AI has given me renewed energy for this framing. Not because AI makes APIs more commercial, even though it often does. It is because AI has made the volume and velocity of API consumption so undeniable that even organizations that spent a decade ignoring the question can’t look away anymore. <a href="https://apievangelist.com/2025/07/07/there-is-only-api-consumption/">As I have been writing lately, there is really only API consumption</a> — everything else is scaffolding in service of getting value from one system into another. AI agents are now doing this at a scale and speed that exposes every gap in how organizations have been thinking about the value flowing through their APIs. The question is no longer whether to think about API value exchange. It is whether you have built the visibility to see it happening.</p>

<p>The renewal I’m feeling is not about AI APIs specifically — the market for those is being worked out loudly and publicly enough. What interests me is how AI-driven consumption is forcing organizations to think carefully about their internal APIs, their partner APIs, and their public APIs simultaneously, often for the first time. These three tiers have always existed. What’s new is the market pressure.</p>

<p><strong>Internal API consumption</strong> is where the question gets ignored most often, and where it matters most. I wrote about this more than a decade ago when I was figuring out my own API stack — <a href="https://apievangelist.com/2014/04/17/the-private-internal-tier-of-my-api-service-composition/">the first consumer of my APIs was me</a>, and I needed to track that usage the same way I tracked any external consumer. Not to bill myself, but to understand the costs, identify unhealthy consumption patterns, and see the full picture of what was flowing through the system. Instagram and Tesla learned this the hard way; their internally-consumed APIs had no management layer, which meant attackers could walk through doors nobody was watching.</p>

<p>In the AI era, internal API consumption is exploding. Every agent, every automated workflow, every LLM-powered feature in your product is an API consumer. Many of these are consuming the same internal APIs that your engineering teams built to serve each other. The value exchange happening at this layer — between your AI infrastructure and your business capabilities — is now significant enough to warrant governance, cost accounting, and visibility. Not because you’re going to charge your own teams, but because you cannot manage what you cannot measure, and the costs are real.</p>

<p><strong>Partner API consumption</strong> is where the value exchange framing does its most useful work. A financial relationship is often present here, but it is rarely the whole story. When I worked on the Recreation.gov RFP, the valuable thing about building a partner API layer wasn’t the per-transaction fees — it was enabling travel planning companies, outdoor recreation apps, and small regional businesses to build on top of federal recreation inventory in ways the government could never staff or fund directly. The value flowing back wasn’t money; it was reach, adoption, feedback, and services delivered to citizens that the government couldn’t deliver itself.</p>

<p>Partner APIs are how organizations extend their capabilities beyond what they can build alone. In the AI era, this is even more true. Your partners are now building AI agents that consume your APIs to automate workflows, extract insights, and create new customer experiences. The terms of that exchange — who gets what value, what obligations come with access, how abuse is prevented — need to be explicit. This is what service composition means in practice: understanding your API consumers well enough to design the tiers of access that make the exchange fair and sustainable for everyone in it.</p>

<p><strong>Public API consumption</strong> is where the public lands analogy remains the most useful in my opinion. The value of making an API public is almost never primarily financial. It is about ecosystem, discoverability, innovation at the edges, and — in the government context — fulfilling a public mission that data belongs to the people who funded its collection. <a href="https://apievangelist.com/2015/09/14/are-there-really-any-monetization-opportunities-around-open-data-and-apis/">The question I was wrestling with in 2015</a> — are there any monetization opportunities around open data and APIs — was a real one, but it was the wrong frame. The question should have been: how do we make the value of this data visible enough to fund its continued maintenance and improvement?</p>

<p>Revenue can be part of the answer. Charging high-volume commercial consumers while keeping access free for researchers, nonprofits, and individual developers is a reasonable model, and one that several government API programs have moved toward. But the goal isn’t to monetize the data. The goal is to sustain the exchange — to keep the data good, keep access open, and grow the ecosystem of things that get built on top of it. That is what public API value exchange means.</p>

<p>I have been at this long enough to know that the hard part is never the framing. Calling it “API value exchange” instead of “API monetization” is only useful if it opens conversations that the other word closed. In government, where I have done some of this work, it does. In enterprise settings, where internal teams are being asked to justify API spending to leadership who didn’t prioritize APIs until AI forced the question, it also helps. In the public data world, where agencies are trying to figure out how to sustain open data programs that are politically popular but chronically underfunded, the value exchange frame gives you something concrete to point at.</p>

<p>The mechanics of this are service composition, rate limits, plan design, cost accounting, partner agreements — haven’t changed much since 2015. What has changed is the urgency, and the volume. AI has cranked up the consumption signal loud enough that the exchange is now impossible to ignore. I intend to spend more time on this framing going forward, connecting the decade-plus of thinking I’ve done on monetization to the reality of what is actually happening at the intersection of AI and APIs right now.</p>]]></content><author><name>Kin Lane</name></author><category term="Value Exchange" /><category term="Monetization" /><category term="Internal" /><category term="Partners" /><category term="Public Data" /><category term="Government" /><category term="AI" /><summary type="html"><![CDATA[I have been writing about API monetization since 2011. Not consistently, but in recurring waves — whenever the business reality of APIs forces itself back to the surface. Early on I was fascinated by the mechanics: resource-based versus experience-based pricing, the cost-to-value accounting framework I tried to formalize, the uncomfortable question of whether open government data could ever generate revenue without betraying its public mission. I spent a lot of time in that era trying to help government agencies — the Forest Service, the National Park Service, the Bureau of Land Management — understand that the value flowing through their APIs was real and worth naming, even if calling it “monetization” was politically untenable.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/1939-new-york-worlds-fair-markets-amsterdam.jpeg" /><media:content medium="image" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/1939-new-york-worlds-fair-markets-amsterdam.jpeg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">History of API Evangelist</title><link href="https://apievangelist.com/2026/06/12/history-of-api-evangelist/" rel="alternate" type="text/html" title="History of API Evangelist" /><published>2026-06-12T00:00:00+00:00</published><updated>2026-06-12T00:00:00+00:00</updated><id>https://apievangelist.com/2026/06/12/history-of-api-evangelist</id><content type="html" xml:base="https://apievangelist.com/2026/06/12/history-of-api-evangelist/"><![CDATA[<p>One story I’ve told many times, but couldn’t find in my own historical archives of API Evangelist, is the origin story of API Evangelist itself. I am learning that the stories I’ve told over the years on API Evangelist provide a lot of context for my use of AI in my research, and filling in the gaps where AI stumbles is proving to be important.</p>

<p>API Evangelist began as an idea in July of 2010, and took form in the first series of blog posts published in September of 2010. At the time I lived in Eugene, OR, had just gotten together with my girlfriend and now wife Audrey Watters. I was looking to move on from a job as VP of Technology at an events management company who was running SAP and Google events in North America. APIs were something I had experience with and seemed interesting.</p>

<p>While running events I had begun to use AWS S3 and EC2 to help me manage the servers I needed for registration, emails, session scanning, and other common conference tasks. In the early days of AWS there weren’t a lot of applications and tools, so I got pretty skilled at working the kung fu I needed to stand up and tear down the servers I needed to support email blasts and the first day of a conference. When I took over the role I had to physically go pull servers out of a storage unit, drive them to the colo facility, and physically install the software I needed. I didn’t have a lot of room for scaling up and down as needed to meet the demand. The cloud changed that, and I saw APIs were a key part of the process.</p>

<p>In 2008 I was running registration for Google I/O, and it was the one where they first launched the Android phone. At the time it was literally a phone they manufactured, as well as the operating system, and every attendee got a phone. Google pushed us to build applications and integrations around their APIs, including Google Wave. Remember Google Wave? This opportunity gave me another chance to see the potential of developing with scrappy, lightweight XML or JSON APIs over HTTP. The need for data and other digital resources over iPhone and now Android lit the fire underneath me — seeing the potential for using HTTP APIs to do everything from the cloud to mobile, forever changing my life and career.</p>

<p>By 2009 I was ready to move on from the event space and began looking for jobs that were related to APIs. I took a brief job with Mimeo, a print company in NYC, and CityGrid, a city data provider in West Hollywood. I used this opportunity to learn more about operating public APIs and portals, and settled on the brand “API Evangelist”, emulating Guy Kawasaki and Jeff Barr, but with an exclusive focus on APIs. At the time I was programming, but I was a pretty insecure programmer with no classical training. So I focused on what I considered to be the business of APIs, instead of the technical details, hoping to build bridges with business stakeholders when it came to what mattered when doing public APIs. The concept of internal APIs wasn’t such a big thing, and was mostly dominated by the concept of service-oriented architecture. But public APIs were exploding with the introduction of Facebook and Twitter, as well as Twilio and Stripe.</p>

<p>At the same time my girlfriend Audrey was looking to establish herself as a writer, and chose to focus on <a href="http://hackeducation.com">Hack Education</a>. She has her masters in folklore and storytelling, which provided the seed of inspiration for my focus on storytelling around APIs. Pausing to write this story, not a lot has changed. I’ve added the politics of APIs to the mix, and I’ve gotten much more confident in my technical chops when it comes to APIs. Storytelling is really the only thing that keeps me going with this work. I love listening to people’s stories about what they do with APIs, and I really enjoy sitting down to write stories about what I’ve heard and learned. I am thankful for the opportunity to publish 5000+ stories here, and the many, many, many conversations I’ve had with people doing interesting things with APIs over the years. It has been an amazing journey, and honestly I can’t see myself ever putting it down, and I hope I can keep it up until the day I step out of this world. I don’t see ever retiring from learning and telling stories about APIs.</p>]]></content><author><name>Kin Lane</name></author><category term="API Evangelist" /><category term="History" /><category term="Origin" /><category term="Storytelling" /><summary type="html"><![CDATA[One story I've told many times, but couldn't find in my own historical archives of API Evangelist, is the origin story of API Evangelist itself. Here it is.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.us-east-1.amazonaws.com/1778714877409.jpeg" /><media:content medium="image" url="https://kinlane-productions2.s3.us-east-1.amazonaws.com/1778714877409.jpeg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Your Diverse API Toolbox</title><link href="https://apievangelist.com/2026/06/12/your-diverse-api-toolbox/" rel="alternate" type="text/html" title="Your Diverse API Toolbox" /><published>2026-06-12T00:00:00+00:00</published><updated>2026-06-12T00:00:00+00:00</updated><id>https://apievangelist.com/2026/06/12/your-diverse-api-toolbox</id><content type="html" xml:base="https://apievangelist.com/2026/06/12/your-diverse-api-toolbox/"><![CDATA[<p>I have been writing about this since <a href="https://apievangelist.com/2017/03/10/focus-on-having-a-robust-and-diverse-api-toolbox/">March 2017</a>, kept expanding it through <a href="http://apievangelist.com/2018/01/02/my-evolving-definition-of-a-robust-and-diverse-api-toolbox/">2018</a> with a diagram that I brought to talks and workshops, and reinforced it again in <a href="https://apievangelist.com/2020/08/31/a-diverse-api-toolbox-is-the-future/">2020</a>. Coming back from APIDays Amsterdam, the same message needs saying again — now with MCP and Agent Skills freshly added to the shelf.</p>

<p>The diagram above is my current read on the toolbox. Every time someone tells you that REST is dead, or that everything will be GraphQL, or that MCP will replace all your APIs, remember: they are a tool salesperson, not a practitioner. The people who get things done across the real enterprise have a diverse set of tools and know when to reach for which one.</p>

<h2 id="api-design-patterns">API Design Patterns</h2>

<p>These are the request/response patterns — the core of how clients talk to servers.</p>

<ul>
  <li><strong>REST</strong> is still the dominant pattern and will remain so. It maps cleanly to the web, it is simple enough that a wide audience can consume it, and it has the broadest tooling support. Every practitioner should be able to design and ship REST APIs well. The limitations are real — deep queries, real-time data, tight coupling between client and server — but none of them mean REST is going away.</li>
  <li><strong>GraphQL</strong> earns its place when consumers need to drive the shape of the response. Data-intensive products, mobile clients, and cases where you want to avoid under/over-fetching are where GraphQL genuinely shines. It also moves the schema front-and-center, which I respect. The tradeoff is complexity on the server and a higher floor for client sophistication.</li>
  <li><strong>gRPC</strong> is the two-speed API. When you need high-volume, low-latency inter-service communication inside a data center or across microservices, gRPC’s binary Protocol Buffers wire format and HTTP/2 multiplexing make a meaningful difference. It does not belong as your public-facing API unless your consumers are large enough to justify it — but it absolutely belongs in the toolbox.</li>
</ul>

<h2 id="event-driven-patterns">Event-Driven Patterns</h2>

<p>The moment your architecture needs to react to something happening rather than being polled for information, you reach for event-driven patterns. The mistake is treating any of these as a full replacement for request/response. They are complementary.</p>

<ul>
  <li><strong>Webhooks</strong> are the simplest push pattern: when something happens, HTTP POST to a URL the consumer registered. Stripe has built their entire developer experience around webhooks. They are asynchronous, decoupled, and nearly universal. Every API platform should offer webhooks before it offers Kafka.</li>
  <li><strong>Event Destinations</strong> is the more mature form of webhooks — where instead of just delivering to a URL, you deliver to configurable targets: S3 buckets, queues, other APIs, third-party services. Stripe, GitHub, and Shopify have all converged on this model. It shifts integration work from bespoke webhook receivers to a routing problem, which is much more tractable at scale.</li>
  <li><strong>WebSockets</strong> open a persistent bidirectional connection. This is for genuinely real-time interactions — chat, live dashboards, collaborative editors, trading feeds. The connection overhead is real, so this is not the right tool for fire-and-forget notifications. Know the difference between “low latency” and “real-time” before you reach for WebSockets.</li>
  <li><strong>Kafka</strong> is industrial-grade event streaming. When you are moving millions of events per second, need replay capability, need durable ordered delivery across many consumers, and need to run at scale across distributed infrastructure — Kafka (and its ecosystem) is the answer. Too many organizations reach for Kafka before they have exhausted simpler patterns. It is powerful and it is complex. Make sure you can operate it reliably before you commit.</li>
</ul>

<h2 id="experience-patterns">Experience Patterns</h2>

<p>These are the patterns that determine whether your API actually gets used. You can ship a technically perfect API and have zero adoption if the experience around it is poor.</p>

<ul>
  <li><strong>Documentation</strong> is not optional. It is the interface between your API and your potential consumers. The bar in 2026 is an interactive reference generated from OpenAPI or AsyncAPI, supplemented by guides that explain how to actually accomplish something with the API rather than just enumerating its endpoints. If your documentation is just a list of routes, it is not documentation — it is a changelog.</li>
  <li><strong>Mock Servers</strong> close the loop between design and development. Consumers should be able to start building against a mock before the real implementation exists. Prism, Mockoon, WireMock — the tooling is mature. If your team cannot create a mock server from an OpenAPI spec in an afternoon, something is wrong with your process.</li>
  <li><strong>Discovery</strong> is the increasingly critical, chronically underinvested pattern. Can your developers find every API available to them? Can an AI agent? I run <a href="https://apis.io">APIs.io</a> specifically because API discovery is a genuinely hard problem that affects everyone doing API integration at scale. APIs.json and well-maintained developer portals are where this gets solved.</li>
</ul>

<h2 id="integration-patterns">Integration Patterns</h2>

<p>How do consumers actually wire your API into their systems?</p>

<ul>
  <li><strong>Clients</strong> are the generated or hand-crafted HTTP client code that wraps the raw HTTP calls. A good client handles authentication, retries, rate limit backoff, and pagination. Auto-generating clients from OpenAPI specs has become table stakes — if you are not generating client libraries, you are creating unnecessary friction.</li>
  <li><strong>SDKs</strong> go beyond clients to provide a higher-level abstraction that fits a specific language’s idioms. The Stripe SDK for Python feels like Python, not like a thin wrapper around HTTP. The gap between a good SDK and a generated client is the difference between adoption and abandonment.</li>
  <li><strong>Copilots</strong> are the AI coding assistants — GitHub Copilot, Claude, Cursor — that now function as first-line integration support. They are only as good as the machine-readable artifacts they can access. An API with a well-structured OpenAPI spec, good descriptions, and examples is vastly more useful to a copilot than one with none of those things. Writing for copilots is writing good API documentation.</li>
  <li><strong>Agents</strong> are the autonomous systems that compose multi-step API calls to accomplish goals without human intervention in each step. This is where MCP and Agent Skills directly feed in. An agent needs to discover what APIs exist, understand what they do, and be able to call them safely and reliably. The toolbox patterns connect: REST and gRPC for the calls, OpenAPI for the contract, MCP as the agent-native access layer.</li>
</ul>

<h2 id="ai-patterns">AI Patterns</h2>

<p>These are new tools in the toolbox as of the last two years, and while they dominate much of the conversation, they are beginning to shrink back down to a realistic cope in our modern toolbox.</p>

<ul>
  <li><strong>MCP (Model Context Protocol)</strong> is Anthropic’s open protocol for how AI models access tools, data, and services. What started as a way to wire Claude into local development environments has become a standard that Microsoft, Google, and hundreds of API providers have adopted. An MCP server exposes your API’s capabilities as tools that an AI model can call directly — with proper auth, schemas, and descriptions. I have been cataloging which providers in my network ship MCP servers. The number growing fast.</li>
  <li><strong>Agent Skills</strong> (SKILL.md) are structured definitions that describe what an agent can do in a portable, discoverable format. Where MCP defines the protocol, a skill definition describes the intent, inputs, outputs, and preconditions of an agent capability. I have been building this out as part of the <a href="https://naftiko.com">Naftiko</a> work. Skills allow agents to compose and delegate in principled ways rather than through freeform instruction.</li>
</ul>

<p>The important thing to understand about MCP and Agent Skills is that they do not replace REST, GraphQL, or any of the other patterns. They sit on top of them. An MCP server typically calls REST APIs internally. An agent skill may orchestrate a sequence of Kafka events and REST calls. The foundation does not go away — you are extending the toolbox, not replacing it.</p>

<h2 id="media-types">Media Types</h2>

<p>One of the things I keep having to remind people: the format your API returns is a design decision with real consequences for who can use your API and how.</p>

<ul>
  <li><strong>application/json</strong> — the lingua franca; assume JSON unless you have a specific reason not to</li>
  <li><strong>application/xml</strong> — still required in enterprise, government, and healthcare integrations; do not pretend it does not exist</li>
  <li><strong>application/yaml</strong> — human-readable and increasingly expected for configuration, specs, and anything a developer will edit directly</li>
  <li><strong>application/csv</strong> — underestimated; a CSV response from a data API means a non-developer can open it in Excel; never underestimate the spreadsheet audience</li>
  <li><strong>application/html</strong> — your API responds with HTML; this is both older than REST and more prevalent than most API designers acknowledge</li>
  <li><strong>text/markdown</strong> — increasingly relevant as LLMs consume API documentation; structured natural language that both humans and models can read</li>
</ul>

<p>Negotiating the right media type is something your toolbox should handle gracefully. An API that can return <code class="language-plaintext highlighter-rouge">application/json</code> when asked and <code class="language-plaintext highlighter-rouge">application/csv</code> when asked is strictly more useful than one that can only do one.</p>

<h2 id="api-specifications">API Specifications</h2>

<p>Machine-readable contracts are the connective tissue of the entire toolbox. Without them, nothing else scales.</p>

<ul>
  <li><strong>OpenAPI</strong> remains the primary contract format for REST APIs. 23,000+ specs indexed on <a href="https://apis.apis.io">apis.apis.io</a>. The tooling ecosystem is enormous. If you are building a REST API and not shipping an OpenAPI spec, you are intentionally making integration harder.</li>
  <li><strong>AsyncAPI</strong> does for event-driven what OpenAPI does for REST. Kafka topics, WebSocket channels, webhooks — AsyncAPI describes them all in a consistent machine-readable format. It remains underinvested relative to its importance.</li>
  <li><strong>JSON Schema</strong> is the data modeling layer that both OpenAPI and AsyncAPI build on. Used directly for validating JSON payloads, generating documentation, and providing type-safe contracts. 95,000+ schemas indexed in my network.</li>
  <li><strong>GraphQL SDL</strong> is the schema definition language for GraphQL APIs — self-documenting, introspectable, the reason GraphQL has the tooling ecosystem it does.</li>
  <li><strong>MCP Spec</strong> defines MCP server capabilities in a machine-readable format — what tools an MCP server exposes, their inputs and outputs, how to auth. The spec is young but stabilizing fast.</li>
  <li><strong>Agent Skills</strong> specification is still evolving. The goal is a portable, platform-agnostic format for describing what an agent can do — composable, discoverable, and grounded in the underlying APIs that make the skills work.</li>
  <li><strong>Protocol Buffers</strong> is the schema format for gRPC — binary, strongly typed, backward compatible. If gRPC is in your toolbox, Protocol Buffers comes with it.</li>
</ul>

<hr />

<p>The lesson from every API cycle — REST, GraphQL, webhooks, Kafka, and now MCP — is that the practitioners who succeed are not the ones who pick the pattern that gets talked about the most. They are the ones who understand the tradeoffs of each tool, know when to reach for which, and can explain those choices to the people around them. The future is not event-driven. It is not AI-native. It is not any single thing. The future is having a diverse API toolbox and knowing how to use it.</p>

<p>That is the message I keep coming back to. That is the message APIDays Amsterdam keeps reinforcing. Maintain your diverse API toolbox and understand where new tools being discussed fit in.</p>]]></content><author><name>Kin Lane</name></author><category term="Toolbox" /><category term="REST" /><category term="GraphQL" /><category term="gRPC" /><category term="Webhooks" /><category term="WebSockets" /><category term="Kafka" /><category term="MCP" /><category term="Agent Skills" /><category term="OpenAPI" /><category term="AsyncAPI" /><category term="Protocols" /><category term="Patterns" /><summary type="html"><![CDATA[Coming back from APIDays Amsterdam, the one thing I keep coming back to is the need to reinforce the idea of a diverse API toolbox. MCP and Agent Skills are settling in alongside REST, GraphQL, Webhooks, and Kafka — and no single pattern will ever rule them all.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/eugenics-old-tools.jpeg" /><media:content medium="image" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/eugenics-old-tools.jpeg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Industrial Manufacturing APIs and the AI Integration Gap</title><link href="https://apievangelist.com/blog/2026/06/05/industrial-manufacturing-apis-and-the-ai-integration-gap/" rel="alternate" type="text/html" title="Industrial Manufacturing APIs and the AI Integration Gap" /><published>2026-06-05T00:00:00+00:00</published><updated>2026-06-05T00:00:00+00:00</updated><id>https://apievangelist.com/blog/2026/06/05/industrial-manufacturing-apis-and-the-ai-integration-gap</id><content type="html" xml:base="https://apievangelist.com/blog/2026/06/05/industrial-manufacturing-apis-and-the-ai-integration-gap/"><![CDATA[<p>I spent the last week cataloging the industrial manufacturing API landscape, doing a proper inventory of what is out there, what APIs providers expose, what vocabulary they use to describe themselves, and what machine-readable artifacts are available for integration. I pulled 421 providers across the manufacturing, industrial automation, IIoT, robotics, SCADA, MES, CMMS, PLM, and supply chain segments. Then I ran an enrichment pipeline across 56 of the most specifically API-facing providers to find out how many had publicly discoverable OpenAPI specifications.</p>

<p>The answer: <strong>five</strong>. Cognite, Limble CMMS, Inductive Automation’s Ignition, Factory I/O, and Formant. Five out of 56 providers that I explicitly selected because they sounded like they had APIs.</p>

<p>That number tells a story worth unpacking, because AI agents need industrial data, the industrial data lives behind systems that don’t always speak REST, and the gap between those two facts is where the next wave of manufacturing AI integration is either going to break through or break down.</p>

<h2 id="what-the-vocabulary-tells-you">What the vocabulary tells you</h2>

<p>Before I get into the AI angle, let me walk through what the tag vocabulary across those 421 providers looks like. The top tags paint a picture of where the industry thinks its API surface lives:</p>

<table>
  <thead>
    <tr>
      <th>Tag</th>
      <th>Count</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Manufacturing</td>
      <td>143</td>
    </tr>
    <tr>
      <td>Industrial</td>
      <td>58</td>
    </tr>
    <tr>
      <td>Supply Chain</td>
      <td>44</td>
    </tr>
    <tr>
      <td>IoT</td>
      <td>36</td>
    </tr>
    <tr>
      <td>Aerospace</td>
      <td>36</td>
    </tr>
    <tr>
      <td>Automotive</td>
      <td>34</td>
    </tr>
    <tr>
      <td>Construction</td>
      <td>40</td>
    </tr>
    <tr>
      <td>Industrial Automation</td>
      <td>12</td>
    </tr>
    <tr>
      <td>Industrial IoT</td>
      <td>16</td>
    </tr>
    <tr>
      <td>SCADA</td>
      <td>clustered under Industrial</td>
    </tr>
    <tr>
      <td>CMMS</td>
      <td>handful</td>
    </tr>
    <tr>
      <td>MES</td>
      <td>handful</td>
    </tr>
  </tbody>
</table>

<p>The big buckets — Manufacturing, Industrial, Supply Chain — are describing what the company does, not what their API surface is. Dig into the more specific operational tags — SCADA, MES, CMMS, PLM, PLC, OPC UA — and the count drops fast. Most companies in this space are not primarily API providers. They are equipment makers, systems integrators, specialty chemical producers, and industrial conglomerates that happen to have some integration capability somewhere in their stack. That distinction matters a lot once you start asking what an AI agent can actually connect to.</p>

<h2 id="the-three-layers-of-the-industrial-api-stack">The three layers of the industrial API stack</h2>

<p>After cataloging all of this, I think the industrial manufacturing API landscape has three reasonably distinct layers, and each has a different relationship with AI integration.</p>

<p><strong>Layer one is the industrial data platform</strong> — Cognite Data Fusion, AVEVA PI (formerly OSIsoft), Siemens MindSphere, Rockwell FactoryTalk DataMosaix. These are the systems that already aggregate time-series sensor data, asset hierarchies, events, and process historian records from the operational technologylayer and make them available over REST. Cognite is the best example: a comprehensive API covering assets, time series, 3D models, entity matching, SQL transformations, serverless functions, and workflow orchestration. It has a proper OpenAPI spec, Python and JavaScript SDKs, and the architecture of a company that treats its API as a product. AVEVA PI similarly exposes a Web API with GET/POST/PUT/PATCH/DELETE operations against historian data. These are the providers where an AI agent can actually do something useful today — they have already solved the hard problem of getting operational technologydata into a form that REST can address.</p>

<p><strong>Layer two is the manufacturing operations platform</strong> — Tulip Interfaces, Rockwell Plex ERP, Epicor Kinetic, Inductive Automation’s Ignition. These sit on or just above the shop floor and manage the operational data that flows through a production run: apps, tables, stations, work orders, quality records, jobs. Tulip has a genuinely clean REST API organized into namespaces — apps, table records, connectors, stations, automations — each independently versioned. Ignition 8.3 now exposes an OpenAPI-compliant gateway API for tag reads, project configuration, and module access, which is a significant signal: SCADA is starting to grow an HTTP surface. Epicor Kinetic exposes everything through OData v4, which is not REST in the way most developers think of it, but it is machine-addressable and has an interactive spec explorer. This layer is where the AI integration story gets genuinely interesting, because it is where the human decisions and production instructions actually live.</p>

<p><strong>Layer three is the maintenance and asset management layer</strong> — CMMS systems like Limble, Fiix (now Rockwell’s), and UpKeep; EAM platforms; condition monitoring vendors like Augury. Limble has one of the cleanest manufacturing APIs I encountered in this exercise: a proper REST API with regional endpoints, Basic auth, and resources covering assets, locations, work orders, preventive maintenance tasks, parts, purchase orders, vendors, and webhooks. It even has a 21 CFR Part 11 compliant endpoint for pharmaceutical manufacturing. UpKeep is similarly solid. This layer is interesting for AI because it holds the maintenance history, failure modes, part lifecycles, and work order patterns that predictive maintenance models need to learn from.</p>

<h2 id="the-operational-technology-floor-is-still-not-on-the-internet">The operational technology floor is still not on the internet</h2>

<p>Below all three of these layers sits the actual operational technology — PLCs, DCS systems, SCADA historians, CNC controllers, field instruments, vision systems. This is where the physical manufacturing happens, and almost none of it speaks REST natively. The protocols are OPC UA, Modbus, PROFINET, MTConnect, EtherNet/IP — industrial protocols designed for deterministic real-time control over hardened networks, not for cloud-native HTTP integrations.</p>

<p>The pipeline run I did confirmed this in clear terms. ABB Robotics: no public API spec, developer documentation is proprietary and gated. FANUC Robotics: no public API, MTConnect adapter available but not REST. KUKA: no public API surface. Honeywell: portal exists, no published spec. Bosch: IoT Suite exists, all probe paths returned 401 or redirects. Boston Dynamics: gated SDK, no REST spec. Yaskawa: application programming interfaces exist for servo controllers, no REST spec.</p>

<p>These are not small companies. These are the companies that build the machines that make almost everything you touch. And the gap between “has some form of API” and “has a publicly discoverable, machine-readable API spec” is enormous in this space.</p>

<h2 id="why-this-matters-for-ai-agents-right-now">Why this matters for AI agents right now</h2>

<p>The current wave of agentic AI is fundamentally a data access problem. An agent is only as useful as the data it can read and the actions it can take. In most enterprise verticals — SaaS, fintech, logistics, healthcare IT — that problem is largely solved because the cloud-native players built REST APIs as their primary interface. An AI agent can hit Stripe, Plaid, Salesforce, Workday, or any of ten thousand other providers and get back structured JSON that it can reason over.</p>

<p>Manufacturing is different. The most important data in a manufacturing operation — real-time sensor readings, production counters, OEE metrics, alarm histories, quality inspection results, tool wear measurements — lives in systems that predate REST by decades and were designed to be isolated from enterprise networks on purpose. The industrial security model treats network isolation as a feature. The AI integration model needs the opposite.</p>

<p>The forward-looking industrial players are bridging this with industrial data platforms as the translation layer. Cognite’s entire value proposition is exactly this: take operational technology data from historians, SCADA systems, and sensors via industrial connectors, contextualize it into a data model that exposes assets, time series, and relationships, then make all of it available over a well-documented REST API. When Cognite and Tulip <a href="https://www.cognite.com/en/company/newsroom/tulip-and-cognite-to-drive-ai-powered-manufacturing-to-increase-production-capacity-by-up-to-45">announced their integration partnership</a>, the stated goal was a 45% increase in production capacity driven by AI — made possible because Cognite’s data fabric connects the operational technologysensor layer to Tulip’s operator-facing applications, and both expose REST APIs that an AI agent can work with. That partnership is a preview of how the integration stack for industrial AI actually needs to be assembled.</p>

<h2 id="the-scada-openapi-signal">The SCADA OpenAPI signal</h2>

<p>One of the more interesting findings from this exercise was Inductive Automation’s decision to add an OpenAPI-compliant REST API to Ignition 8.3. Ignition is the dominant SCADA platform for mid-market and enterprise manufacturing — tens of thousands of deployments across water treatment, food production, oil and gas, discrete manufacturing. It has always been deeply extensible through Python scripting, OPC UA, MQTT, and a module ecosystem. Adding an OpenAPI gateway that documents tags, projects, device connections, and module routes as REST resources is a meaningful shift.</p>

<p>It is not cloud-native REST in the Stripe sense. The base URL is <code class="language-plaintext highlighter-rouge">https://{gateway-host}:8088/api</code> — this is a local or on-premise gateway, not a SaaS endpoint. But the fact that the spec is generated dynamically from installed modules, is OpenAPI 3.0 compliant, and logs all mutative operations to audit trails means it is now a surface that integration tools and AI agents can discover and address programmatically. That matters. The question of how an AI agent talks to a SCADA system is a question that has not had a clean answer until now.</p>

<h2 id="what-is-still-missing">What is still missing</h2>

<p>The honest assessment is that the industrial manufacturing API space has most of the pieces and almost none of the connective tissue.</p>

<p>The industrial data platforms exist and have good APIs. The operations platforms are growing REST surfaces. The CMMS layer has mature APIs. The operational technologyequipment layer has industrial protocols and some modern adapters. What is almost entirely absent is:</p>

<p><strong>Standardized schemas.</strong> OPC UA has an information model, MTConnect has a schema, but neither maps cleanly to what a REST API returns. There is no manufacturing equivalent of the FHIR standard in healthcare — a common data model for production orders, quality records, equipment states, and maintenance events that every vendor agrees to. Every provider defines their own object model, which means every integration has to be built from scratch.</p>

<p><strong>Publicly discoverable specs.</strong> Of the 56 most API-forward industrial providers I examined, only five had a spec I could find through normal discovery paths. That is not necessarily because the APIs do not exist — some do — but because the culture in industrial software treats API documentation as a competitive asset to be gated behind enterprise sales conversations rather than published on a developer portal. Cognite and Limble are outliers in treating their specs as open, discoverable artifacts.</p>

<p><strong>Agentic tooling designed for operational technology constraints.</strong> The AI agent frameworks being built today — LangChain, the Anthropic tool-use ecosystem, Microsoft’s Semantic Kernel — assume REST APIs with JSON responses and short latency. Industrial systems have real-time constraints, safety interlocks, and data rates that do not fit those assumptions. An AI agent that misreads a latency spike as a sensor failure and triggers a SCADA alarm is worse than no agent at all. The interface standards for AI agents interacting with operational technologysystems safely have not been written yet.</p>

<h2 id="the-decade-ahead">The decade ahead</h2>

<p>The MES market is at $15.2 billion today and projected to reach $28.5 billion by 2030. OT/IT convergence is accelerating — BCG estimates adoption of converged IT/OT infrastructure for new manufacturing projects will go from roughly 10% to 50% within five years. The manufacturing sector is moving from static dashboards to what the industry is calling agentic AI: systems that can perceive plant conditions, reason over historical data, and take action through the control layer.</p>

<p>All of that requires APIs. The industrial data platforms are ready. The operations layer is getting ready. The operational technologyfloor is being connected, layer by layer, through industrial IoT gateways, MQTT brokers, OPC UA aggregators, and — increasingly — REST wrappers.</p>

<p>What I cataloged in the API Evangelist network this week is a snapshot of where this transition stands in mid-2026. 421 providers touching the manufacturing space, most of them describing themselves in terms of what they make rather than what their integration surface looks like. Five publicly discoverable OpenAPI specs out of the 56 most API-facing providers I examined. A handful of companies — Cognite, Tulip, Limble, Inductive Automation — who have figured out that treating the API as a product is how you become the integration layer for the next generation of manufacturing intelligence.</p>

<p>The gap between those five and the other fifty-one is where the real work of industrial AI integration will happen over the next decade. The factory floor has an enormous amount of data. Getting it into a form that an AI agent can reason over is the hard problem, and the API surface is where it gets solved or does not.</p>

<p><em>All provider data is from the API Evangelist network catalog, enriched as of June 2026. Pipeline results reflect publicly discoverable OpenAPI specifications only — many providers have gated or proprietary API documentation not captured here.</em></p>]]></content><author><name>Kin Lane</name></author><category term="Blog" /><category term="Manufacturing" /><category term="Industrial" /><category term="IIoT" /><category term="SCADA" /><category term="MES" /><category term="Digital Twin" /><category term="AI Agents" /><category term="OT/IT Convergence" /><category term="APIs" /><category term="Industrial Automation" /><summary type="html"><![CDATA[I cataloged 421 industrial manufacturing API providers in my network and ran a pipeline across 56 of the most API-specific ones. Only 5 had a publicly discoverable OpenAPI spec. That gap — between the richness of the industrial data stack and the poverty of its API surface — is exactly where the next wave of AI integration is going to either succeed or stall.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/citizenship-shipping-docs-cranes.jpg" /><media:content medium="image" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/citizenship-shipping-docs-cranes.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The APIs of the World’s Top Universities — 634 of Them, and Most Are Library Plumbing</title><link href="https://apievangelist.com/blog/2026/06/04/the-apis-of-the-worlds-top-universities/" rel="alternate" type="text/html" title="The APIs of the World’s Top Universities — 634 of Them, and Most Are Library Plumbing" /><published>2026-06-04T00:00:00+00:00</published><updated>2026-06-04T00:00:00+00:00</updated><id>https://apievangelist.com/blog/2026/06/04/the-apis-of-the-worlds-top-universities</id><content type="html" xml:base="https://apievangelist.com/blog/2026/06/04/the-apis-of-the-worlds-top-universities/"><![CDATA[<p>I pulled the API surface for 219 of the world’s top-ranked universities — the QS World University Rankings 2025 set that I built into the API Evangelist network — and went looking for the interesting stuff. Which schools publish the most? Which countries show up? And what kind of APIs do universities actually have?</p>

<p>The answer to that last question reframes the whole exercise. Across those 219 schools I cataloged <strong>634 APIs spanning 40 countries</strong>, and the overwhelming majority of them exist for one reason: the university library runs an institutional repository, and that repository speaks OAI-PMH. <strong>84% of these universities (185 of 219) expose a repository or OAI-PMH style API. Only 16% (35 of 219) run anything that looks like a modern developer program</strong> — a portal, OAuth, a gateway, an open-data API. The world’s best universities are sitting on an enormous amount of structured data and have almost no front door to it.</p>

<h2 id="where-the-universities-are">Where the universities are</h2>

<p>Europe dominates the profiled set, which tracks with how QS weights its rankings:</p>

<table>
  <thead>
    <tr>
      <th>Region</th>
      <th>Universities</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Europe</td>
      <td>88</td>
    </tr>
    <tr>
      <td>North America</td>
      <td>51</td>
    </tr>
    <tr>
      <td>Asia</td>
      <td>40</td>
    </tr>
    <tr>
      <td>Oceania</td>
      <td>21</td>
    </tr>
    <tr>
      <td>Middle East</td>
      <td>7</td>
    </tr>
    <tr>
      <td>South America</td>
      <td>2</td>
    </tr>
    <tr>
      <td>Africa</td>
      <td>1</td>
    </tr>
  </tbody>
</table>

<p>By country, the United States leads with 39, then the United Kingdom (27), Australia (16), Germany (12), Canada and the Netherlands (11 each), China and Japan (9 each), and Switzerland (7). Australia massively over-indexes for its size — sixteen schools — and the Netherlands punching at eleven is a reminder that the Dutch have treated research data as public infrastructure for a long time.</p>

<h2 id="what-a-university-api-actually-is">What a “university API” actually is</h2>

<p>Here are the most common API tags across all 634 APIs. Read this list top to bottom and the story tells itself:</p>

<ul>
  <li><strong>Repository (205), OAI-PMH (205)</strong> — the Open Archives Initiative Protocol for Metadata Harvesting. This is the plumbing search engines and aggregators use to harvest a library’s catalog.</li>
  <li><strong>Research (185), Metadata (170), Open Access (148), Open Data (142)</strong></li>
  <li><strong>Library (135), Research Data (98)</strong></li>
  <li><strong>REST (84)</strong> — only now do we get to the thing most people mean when they say “API.”</li>
  <li><strong>DSpace (76), Institutional Repository (60), EPrints (28), Dataverse (24), Pure (21), Figshare (19)</strong> — the repository platforms themselves.</li>
  <li><strong>Identity (68), Authentication (66), SSO (47), Shibboleth (30), SAML (30)</strong> — campus single sign-on, mostly federated through the academic identity systems.</li>
  <li><strong>Education (51), Courses (33)</strong> — course catalogs and timetables.</li>
</ul>

<p>So the typical “API” at a top university is not a developer product. It is a metadata harvesting endpoint that a librarian stood up — or more likely that came bundled with DSpace, EPrints, Figshare, Dataverse, or Pure — exposing the institution’s research output to the world. That is genuinely valuable, machine-readable, and open. It is also almost never documented, versioned, or framed as something a developer should build on.</p>

<h2 id="the-schools-doing-the-most">The schools doing the most</h2>

<p>Counting raw API surface, here are the leaders:</p>

<table>
  <thead>
    <tr>
      <th>APIs</th>
      <th>University</th>
      <th>Country</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>8</td>
      <td>UCL (University College London)</td>
      <td>United Kingdom</td>
    </tr>
    <tr>
      <td>8</td>
      <td>University of California, Santa Barbara</td>
      <td>United States</td>
    </tr>
    <tr>
      <td>6</td>
      <td>ETH Zurich</td>
      <td>Switzerland</td>
    </tr>
    <tr>
      <td>6</td>
      <td>University of Pennsylvania</td>
      <td>United States</td>
    </tr>
    <tr>
      <td>6</td>
      <td>UCLA</td>
      <td>United States</td>
    </tr>
    <tr>
      <td>6</td>
      <td>KU Leuven</td>
      <td>Belgium</td>
    </tr>
    <tr>
      <td>6</td>
      <td>Shanghai Jiao Tong University</td>
      <td>China</td>
    </tr>
    <tr>
      <td>6</td>
      <td>University of Padua</td>
      <td>Italy</td>
    </tr>
  </tbody>
</table>

<p>What separates the top of this list is that a few of these schools went past the repository and built a real developer surface.</p>

<p><strong>UCL</strong> is the clearest example of a university that operates like an API provider. Its <a href="https://uclapi.com">UCL API</a> program publishes Room Bookings, Timetable, Search, Workspaces, and Resources endpoints behind a proper OAuth flow — built largely by and for students, but a legitimate developer portal. That is what a university developer program looks like, and almost nobody else has one.</p>

<p><strong>University of Pennsylvania</strong> is the other standout: a Penn OpenData API, official Penn SDKs in Python and Node, a Penn Courses (PCX) API, and a Penn Course Review API. Again, much of this grew out of student developer culture, but the result is a usable, SDK-backed surface.</p>

<p><strong>UC Berkeley</strong> is the institutional version of the same idea — “API Central,” an actual developer portal, sitting in front of a UC Berkeley API Gateway, plus the eScholarship repository and Alma/Primo library integrations underneath.</p>

<h2 id="the-interesting-corners">The interesting corners</h2>

<p>The fun is in the outliers — the APIs that aren’t just another repository harvest endpoint:</p>

<ul>
  <li><strong>Caltech</strong> exposes the <strong>IRSA Virtual Observatory APIs</strong> through IPAC — astronomy data infrastructure, which is exactly the kind of thing you hope a place like Caltech puts on the open web.</li>
  <li><strong>ETH Zurich</strong> has the most interesting <em>library</em> surface of the bunch: a Geo Information API, a Persons API, a Vector API, and ETHorama alongside the expected Research Collection — the Swiss treating the library as a data platform.</li>
  <li><strong>Shanghai Jiao Tong University</strong> publishes a <strong>Data Resources GraphQL API</strong> — the only GraphQL surface I saw in the entire set, and notable for coming out of mainland China.</li>
  <li><strong>EPFL</strong> runs a <strong>Memento Events API</strong> — campus events as a feed.</li>
  <li><strong>Columbia</strong> exposes a <strong>CU Directory of Classes</strong>, and <strong>NUS</strong> has the community-built <strong>NUSMods API</strong> (unofficial, but the most-used student API in Singapore).</li>
</ul>

<p>And the repository platforms read like a who’s-who of scholarly infrastructure: DSpace at NUS (ScholarBank), EPrints at Southampton (which is fitting — EPrints was born at Southampton), Figshare at the University of Hong Kong, Dataverse at NTU, Pure at Edinburgh, and Alma/Primo at Berkeley.</p>

<h2 id="what-this-tells-me">What this tells me</h2>

<p>Universities are not behind on APIs in the way most enterprises are. They are behind in a <em>different</em> way. A Fortune 1000 company usually has the developer program and is missing the open data. The top universities have the open data — enormous, structured, machine-readable research output — and are missing the developer program. The data is already there, already public, already speaking a standard protocol. What is almost entirely absent is the front door: documentation, a portal, OAuth where it is needed, and the basic acknowledgment that the OAI-PMH endpoint a librarian configured a decade ago is, in fact, an API that someone could build on.</p>

<p>The schools at the top of my count — UCL, Penn, Berkeley — figured this out, and in every case it was the institution choosing to treat its data like a product. The other 184 are one developer portal away from being genuinely useful to the outside world. The plumbing is already in the walls.</p>

<p><em>Profiled from the QS World University Rankings 2025 set in the API Evangelist network. Counts reflect what I have cataloged, not necessarily every API each school operates; a handful of entries (like NUSMods) are community-built rather than official, and are flagged as such in the profiles.</em></p>]]></content><author><name>Kin Lane</name></author><category term="Blog" /><category term="Universities" /><category term="Higher Education" /><category term="APIs" /><category term="OAI-PMH" /><category term="Open Access" /><category term="Research Data" /><category term="Institutional Repository" /><category term="Developer Portals" /><category term="API Discovery" /><category term="Education" /><summary type="html"><![CDATA[I profiled the API surface of 219 of the world's top-ranked universities — the QS 2025 set — and found 634 APIs across 40 countries. The headline isn't the count. It is that 84% of these schools expose an API only because their library runs an institutional repository that speaks OAI-PMH, and just 16% run anything resembling a real developer program. The world's best universities have an enormous amount of structured data and almost no front door to it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/john-wayne-the-searchers-aov6mV1n7VGeQ.jpg" /><media:content medium="image" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/john-wayne-the-searchers-aov6mV1n7VGeQ.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Obtaining the Control Over Your LinkedIn Data That You Desire</title><link href="https://apievangelist.com/blog/2026/06/03/obtaining-the-control-over-your-linkedin-data-that-you-desire/" rel="alternate" type="text/html" title="Obtaining the Control Over Your LinkedIn Data That You Desire" /><published>2026-06-03T00:00:00+00:00</published><updated>2026-06-03T00:00:00+00:00</updated><id>https://apievangelist.com/blog/2026/06/03/obtaining-the-control-over-your-linkedin-data-that-you-desire</id><content type="html" xml:base="https://apievangelist.com/blog/2026/06/03/obtaining-the-control-over-your-linkedin-data-that-you-desire/"><![CDATA[<p>I have ranted several times about how tightly LinkedIn controls our personal user data. They refuse to give you access to your personal profile data via the LinkedIn API. You can access your company pages via the API, but everything is centered around your desire to run LinkedIn ads. I simply want access to MY data via the platform. I am not asking for much. I have tried every SaaS and Chrome extension out there that promises to do this for you, and have been unable to obtain access to my data daily in the manner that I wish. It is unacceptable.</p>

<p>I am not one to be deterred, and usually will find a way to get what I want. I finally did. You don’t have to be a programmer to do this, but you have to be technically brave. Another caveat and assumption. I use the Claude VSCode extension to do this, which gives you more file-level access to many files—which transforms how you use Claude. I highly recommend it, even if you aren’t a programmer. Like GitHub, you don’t have to write code to use VSCode—it is just an editor. I don’t have the time right now to work out all the details using Claude desktop, web, or via ChatGPT or Gemini—if you need that, let me know, maybe sweet talk or pay me, and I may be able to prioritize one of these solution paths. Let me know.</p>

<h2 id="fiddler-everywhere">Fiddler Everywhere</h2>

<p>This journey begins with downloading <a href="https://www.telerik.com/download/fiddler-everywhere">Fiddler Everywhere</a>, a modern, cross-platform web debugging proxy and traffic analyzer available for Windows, macOS, and Linux. It captures, inspects, mocks, and modifies HTTP and HTTPS traffic between your machine and the internet.</p>

<p>Turn it on and capture all traffic. Again, you don’t have to be a programmer, but you need to be technically unafraid, and it is a tool that will open up a whole new world for you if you do. It is a gateway drug to APIs, and you will see the digital world differently once you get acquainted with it.</p>

<h2 id="linkedin">LinkedIn</h2>

<p>Once you’ve downloaded and installed Fiddler Everywhere, open it up and you will immediately see traffic from across EVERY website you visit, and everything behind it flowing through Fiddler. Now visit LinkedIn. Spend some time browsing through all of the types of data you wish to capture. Here is a list of the LinkedIn entities I browse to get what I needed.</p>

<ul>
  <li><strong>Posts</strong> - Posts I submitted or shared. I try to stay off the home page.</li>
  <li><strong>Reactions</strong> - Opening up the full list of reactions to each post.</li>
  <li><strong>Profiles</strong> - Clicking open the profile pages of people I am interested in.</li>
  <li><strong>Messages</strong> - Opening up messages, replying, and scrolling up and down.</li>
  <li><strong>Groups</strong> - Opening up the groups I manage or am part of and scrolling down.</li>
</ul>

<p>Fiddler will only record what you load, so scroll around, click and load what you want. Stay off the things you don’t want. I recommend staying in your notifications, mentions, and groups, but you can open up the profile of people you want to “profile” and view their page and activity. I regularly use this to find out what people are interested in, by gathering what they have posted and what they have shared.</p>

<h2 id="filtering">Filtering</h2>

<p>Once you are done exploring LinkedIn and are ready to process your activity for the day or any given moment, maybe after research, click on the filters button in Fiddler, and add a URL Contains filter for <code class="language-plaintext highlighter-rouge">https://www.linkedin.com</code>. It will list all of the traffic just for LinkedIn. Highlight everything by hitting command or control all, right click and choose export RAW file. Put it somewhere you remember, so you can direct Claude to it via a path you will need to update via the Agent Skill I have provided below.</p>

<p>This is a process you can do for any website. It isn’t limited to LinkedIn, but the Agent Skill I provide is only for LinkedIn. The same approach will work for any website or application you use, but the entities you capture will be relative to the platform. It just depends on what you capture and are looking to mine. This is what makes Fiddler so powerful. You can leave it on all day and paint a picture of your entire digital footprint. Warning though, there are some sites where having a proxy open will screw with things, so be aware. I leave it on all the time and then a website doesn’t load or I get wonky things.</p>

<h2 id="agent-skill">Agent Skill</h2>

<p>I have created an Agent Skill to guide each time I do this, and I am happy to share it with you. I’ve pasted it here via a GitHub Gist, but you will need to download it locally and edit it. You will need to update the <code class="language-plaintext highlighter-rouge">[local path]</code> location which exists throughout the skill with the local path where you save your Fiddler RAW file containing all your LinkedIn traffic. Make sure to read the entire Agent Skill. Again, you don’t need to be a coder to do this, it is plain enough English that you should be able to follow. NEVER trust an Agent Skill file from anyone—even me. It is easy to put malicious things in there that can mess with your world.</p>

<p>I save the Agent Skill to the <code class="language-plaintext highlighter-rouge">.claude/skills</code> folder in the project I have VSCode open to, which I then save my Fiddler file to <code class="language-plaintext highlighter-rouge">social/linkedin/*</code>—you will have to navigate this on your end, and update the path accordingly. Like I said earlier, if you want to do this via Claude desktop, web, or Gemini and ChatGPT, it is a separate process, but the same approach and skills will work, but the file system voodoo will vary.</p>

<p>Here is the full Agent Skill (you can also <a href="https://gist.github.com/kinlane/fa938f842c7b0a75432685a1a9b87c34">download the raw file from the GitHub Gist</a>):</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">parse-linkedin</span>
<span class="na">description</span><span class="pi">:</span> <span class="s">Parse a Fiddler Everywhere RAW export of LinkedIn (Voyager API) traffic into markdown lists of Posts, Reactions, Profiles, Messages, and Groups. Use when a LinkedIn capture into social/linkedin/ is dropped and wants it turned into readable lists.</span>
<span class="na">user_invocable</span><span class="pi">:</span> <span class="no">true</span>
<span class="nn">---</span>

<span class="gh"># LinkedIn — Fiddler capture parser</span>

 Captures LinkedIn web traffic in Fiddler Everywhere and exports the <span class="gs">**RAW**</span>
capture into a dated folder under:

<span class="p">```</span><span class="nl">
</span>[local path]social/linkedin/&lt;YYYY-MM-DD-HHMMSS&gt;/
<span class="p">```</span>

Fiddler saves each captured HTTP <span class="gs">**response body**</span> as a file on disk, laid out
as <span class="sb">`&lt;dump&gt;/&lt;hostname&gt;/&lt;url-path&gt;[index]`</span>. The signal lives under
<span class="sb">`www.linkedin.com/voyager/api/*`</span> — LinkedIn's internal "Voyager" JSON API. Each
file is one JSON response body (no HTTP headers). The bodies are
<span class="sb">`$type`</span>-discriminated entity graphs.

This skill turns that raw network exhaust into five readable markdown lists:
<span class="p">
-</span> <span class="gs">**Posts**</span> — feed updates (<span class="sb">`feed.Update`</span>): author, age, commentary text, permalink
<span class="p">-</span> <span class="gs">**Reactions**</span> — likes/etc (<span class="sb">`social.Reaction`</span>): reactor name, headline, target activity
<span class="p">-</span> <span class="gs">**Profiles**</span> — people seen (<span class="sb">`identity.profile.Profile`</span>): name, headline, premium, profile link
<span class="p">-</span> <span class="gs">**Messages**</span> — DMs (rich messenger graph under <span class="sb">`voyagerMessagingGraphQL/`</span>):
  grouped by conversation, showing who each thread was <span class="gs">**with**</span>, a permalink to
  the thread, and every captured message (timestamp, sender, text; the user's
  own outbound messages are labelled <span class="gs">**Me**</span>)
<span class="p">-</span> <span class="gs">**Groups**</span> — groups seen (<span class="sb">`groups.Group`</span>): name, member count, visibility, link

<span class="gu">## When to invoke</span>
<span class="p">
-</span> "Parse the LinkedIn export"
<span class="p">-</span> "Turn the latest LinkedIn capture into lists"
<span class="p">-</span> "What posts/reactions/messages are in social/linkedin?"
<span class="p">-</span> <span class="sb">`/linkedin-parse`</span>

<span class="gu">## Steps</span>
<span class="p">
1.</span> <span class="gs">**Run the parser.**</span> It defaults to the newest dated dump under
   <span class="sb">`social/linkedin/`</span>.
   <span class="p">```</span><span class="nl">bash
</span>   <span class="nb">cd</span> <span class="o">[</span><span class="nb">local </span>path]
   python3 <span class="o">[</span><span class="nb">local </span>path].claude/skills/linkedin-parse/parse_linkedin.py
   <span class="c"># or a specific dump:</span>
   python3 <span class="o">[</span><span class="nb">local </span>path].claude/skills/linkedin-parse/parse_linkedin.py <span class="o">[</span><span class="nb">local </span>path]social/linkedin/2026-06-03-154246
   <span class="p">```</span>
   It writes to <span class="sb">`social/linkedin/_reports/&lt;dump-name&gt;/`</span>:
<span class="p">   -</span> <span class="sb">`posts.md`</span>, <span class="sb">`reactions.md`</span>, <span class="sb">`profiles.md`</span>, <span class="sb">`messages.md`</span>, <span class="sb">`groups.md`</span>
<span class="p">   -</span> <span class="sb">`README.md`</span> — index with counts
<span class="p">   -</span> <span class="sb">`data.json`</span> — structured sidecar for downstream tooling
<span class="p">
2.</span> <span class="gs">**Read the generated reports**</span> (or just the counts the script prints). Don't
   paste whole files backm. Give a short briefing: counts per
   list, plus 2–4 highlights (notable posts in the feed, who reacted to Kin's
   posts, any inbound message threads, new groups).

<span class="gu">## How it works (so you can answer questions about it)</span>
<span class="p">
-</span> Walks every JSON body under <span class="sb">`www.linkedin.com/voyager/api/`</span> (recursively, so
  it reaches subdirs like <span class="sb">`voyagerMessagingGraphQL/`</span>), visiting every dict node.
<span class="p">-</span> <span class="gs">**Name resolution:**</span> LinkedIn profile URNs are opaque (<span class="sb">`ACoAA...`</span>). For the
  feed, names come from <span class="sb">`ActorComponent`</span> (post author) and <span class="sb">`EntityLockupViewModel`</span>
  (reaction reactor) blocks, each pairing a display name with a <span class="sb">`*profile`</span> URN in
  its image attributes. For messages, names come from the messenger graph's
  <span class="sb">`MessagingParticipant`</span> records — <span class="sb">`participantType.member`</span> gives first/last name
  and profile URL, <span class="sb">`participantType.custom`</span> gives sponsored-InMail names, and
  company participants fall back to captured <span class="sb">`Company`</span> names.
<span class="p">-</span> <span class="gs">**Messages**</span> are decoded from the rich messenger graph (<span class="sb">`_type`</span>-keyed, e.g.
  <span class="sb">`com.linkedin.messenger.Conversation`</span> / <span class="sb">`.Message`</span>, not the older <span class="sb">`$type`</span>
  format). The viewer ("Me") is the first profile in each conversation URN tuple;
  everyone else in the roster becomes the thread's "with". Thread permalinks come
  from each conversation's <span class="sb">`conversationUrl`</span>. Output is grouped by conversation,
  sorted most-recent-first, messages chronological within a thread.
<span class="p">-</span> De-dupes by entity URN / activity id / message backend URN so the same item
  appearing across multiple captured responses is listed once.
<span class="p">-</span> It does <span class="gs">**not**</span> parse anything outside <span class="sb">`voyager/api`</span>. Coverage is whatever
  threads/messages were loaded in the browser while capturing — an unnamed
  "Unknown" thread just means that participant's name was never in the capture.

<span class="gu">## Notes / limits</span>
<span class="p">
-</span> Coverage depends entirely on what is scrolled past while capturing. A bigger
  list means more was loaded in the browser, not that more exists.
<span class="p">-</span> Profiles often have no name (only the headline) when the profile was returned
  without ever appearing in a feed/reaction lockup. Those still list by headline
  and profile link.
<span class="p">-</span> Re-running is safe and idempotent — it overwrites the report folder for that
  dump.

<span class="gu">## Related</span>
<span class="p">
-</span> <span class="sb">`me-daily`</span> skill summarizes the <span class="ge">*same kind*</span> of Fiddler dumps at the
  host/category level (who was talked to). This skill goes the other way:
  decoding the LinkedIn response bodies into actual content lists.
</code></pre></div></div>

<h2 id="markdown-files">Markdown Files</h2>

<p>The reason I like using Claude as an extension in VSCode is that it is easy for Claude to work with entire folders of files, like the Fiddler RAW export, but also it can then easily output multiple markdown files. I had it dump a <code class="language-plaintext highlighter-rouge">groups.md</code>, <code class="language-plaintext highlighter-rouge">messages.md</code>, <code class="language-plaintext highlighter-rouge">posts.md</code>, <code class="language-plaintext highlighter-rouge">profiles.md</code>, and <code class="language-plaintext highlighter-rouge">reactions.md</code>, as well as a <code class="language-plaintext highlighter-rouge">README.md</code> and <code class="language-plaintext highlighter-rouge">data.json</code> dump for each time I run a report. Then I can reference the context for a specific research session, day, or other bounded context I wish. It gives me full control over my data, within the bounded context that matters to whatever I am trying to accomplish.</p>

<h2 id="my-linkedin-data">My LinkedIn Data</h2>

<p>I’ve done this work to satisfy my needs. Giving me control over my LinkedIn data. But I am sharing it in response to a couple friends who have asked for how to do it. They’ve been struggling to get control of their data, frustrated with having to request their entire archive from LinkedIn, or getting warned for using Chrome extensions and other methodologies. This approach gives you full control over your data locally on a daily or other basis, and what you do with the data is up to you. Claude can easily work across the folders and markdown files in VSCode, but you will need to refine if you don’t use VSCode.</p>

<p>I’ve published a video below to walk through some of it to try and outline the steps. But it would need much more work to refine and turn into a tutorial that anyone can follow. So you will have to accept this unpolished story and video, and if you need more help feel free to reach out. I am happy to help and make more time to refine, but for my purposes it has accomplished what I needed, and I am using it daily to align my LinkedIn reality with my Gmail, Google Calendar, Bluesky, YouTube, and other activities. Storing all my data locally as markdown, which I then sync using GitHub and Amazon S3, and then using Claude to help me make sense of my world in real-time, without having to play the games that LinkedIn, and many other platform providers, make us play.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/6HktUZdnMBU?si=plfd1sQX9ylQU8Vx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>]]></content><author><name>Kin Lane</name></author><category term="Blog" /><category term="LinkedIn" /><category term="Personal Data" /><category term="Data Ownership" /><category term="Data Portability" /><category term="Fiddler Everywhere" /><category term="Claude" /><category term="Agent Skills" /><category term="APIs" /><category term="Privacy" /><summary type="html"><![CDATA[I have ranted several times about how tightly LinkedIn controls our personal user data. They refuse to give you access to your personal profile data via the LinkedIn API. I simply want access to MY data via the platform. I am not asking for much. I am not one to be deterred, and I usually will find a way to get what I want. I finally did, and you don't have to be a programmer to do this — but you have to be technically brave.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/server-cloud-server-racks-clouds-copper-circuit.jpg" /><media:content medium="image" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/server-cloud-server-racks-clouds-copper-circuit.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Automated Agent Onboarding Is a Naftiko Capability, Not a Gateway Feature</title><link href="https://apievangelist.com/blog/2026/05/27/automated-agent-onboarding-as-a-naftiko-capability/" rel="alternate" type="text/html" title="Automated Agent Onboarding Is a Naftiko Capability, Not a Gateway Feature" /><published>2026-05-27T00:00:00+00:00</published><updated>2026-05-27T00:00:00+00:00</updated><id>https://apievangelist.com/blog/2026/05/27/automated-agent-onboarding-as-a-naftiko-capability</id><content type="html" xml:base="https://apievangelist.com/blog/2026/05/27/automated-agent-onboarding-as-a-naftiko-capability/"><![CDATA[<p>An agent shows up at your API. Not a developer. An agent — Claude doing research for someone, an OpenAI Operator running a task for a user, a first-party agent your own company built. It carries a verifiable identity (a signed request, per <a href="https://datatracker.ietf.org/doc/draft-meunier-web-bot-auth-architecture/">Web Bot Auth</a> over <a href="https://www.rfc-editor.org/rfc/rfc9421.html">RFC 9421</a>), a published purpose, and a list of scopes it would like. It would like a credential. It would like to start calling APIs. It would like to do this in one round trip, without waiting two business days for a Slack message from a developer relations person who is also juggling four other things.</p>

<p>Your existing API management platform does not do this for you currently out of the box.</p>

<p>I spent the last week looking through every API gateway and API management OpenAPI in <a href="https://github.com/api-evangelist">my API Evangelist network</a> — Kong, Apigee, Tyk, WSO2, Gravitee, AWS API Gateway, Azure APIM, Google Cloud API Gateway, MuleSoft, Workato, and  others — looking for the operations that would compose into an “agent shows up and self-registers” flow. The operations exist. Every Tier 1 gateway can create a developer, create an app, issue a scoped key, attach a rate limit policy, and stream an audit event. The pieces are there. What’s missing is the <em>composition</em> — the single endpoint that takes a signed onboarding request and orchestrates the three-to-five gateway calls needed to turn it into a credential the agent can use. No gateway has shipped that endpoint.</p>

<p>I see this as the job of a <a href="https://naftiko.io">Naftiko Capability</a>.</p>

<h2 id="the-flow">The Flow</h2>

<p>What the agent experience needs to look like:</p>

<ol>
  <li>Agent fetches <code class="language-plaintext highlighter-rouge">/.well-known/api-catalog</code> per <a href="https://www.rfc-editor.org/rfc/rfc9264">RFC 9264</a>. The catalog includes an <code class="language-plaintext highlighter-rouge">x-onboarding</code> extension pointing at the consent document, the supported signature scheme, and which scopes auto-issue versus require approval.</li>
  <li>Agent fetches <code class="language-plaintext highlighter-rouge">/skills/onboard-agent.md</code> from the provider’s published agent skills directory. The skill is the operating manual — it tells the agent how to construct the request.</li>
  <li>Agent computes a SHA-256 hash of the consent document it just read.</li>
  <li>Agent constructs an HTTP signature over its onboarding request (per <a href="https://datatracker.ietf.org/doc/draft-meunier-web-bot-auth-architecture/">Web Bot Auth</a>), includes the consent hash, the skill ID, the requested scopes, and an operator contact, and POSTs to <code class="language-plaintext highlighter-rouge">/onboard</code>.</li>
  <li>The provider’s edge worker verifies the signature, calls the onboarding capability behind it, and returns a scoped credential. Or, for scopes that need human approval, returns a <code class="language-plaintext highlighter-rouge">202 Accepted</code> with a status URL the agent polls.</li>
</ol>

<p>One round trip for the auto-issuable scopes. A clean async-with-status pattern for the rest. The agent never sees the gateway. The gateway never sees the Web Bot Auth signature. The capability is the seam.</p>

<h2 id="why-its-a-capability-not-a-gateway-feature">Why It’s a Capability, Not a Gateway Feature</h2>

<p>I have been blah blah blahing about Naftiko Capabilities for most of 2026. The shorthand: a Naftiko Capability is a declarative, domain-aligned unit of integration. It composes operations across one or more underlying services, and produces consistent surfaces (REST, MCP, Agent Skills) on top of whatever inconsistent operations sit underneath. You can <a href="https://apievangelist.com/2026/04/14/questioning-our-api-governance-reality/">generate them from OpenAPIs</a>. You can <a href="https://github.com/api-evangelist/palo-alto-networks">govern them with Spectral rules</a>. You can run them through the <a href="https://naftiko.io">Naftiko Framework (Ikanos)</a> on top of whatever existing API or data source sits behind them.</p>

<p>The agent onboarding flow is a <em>textbook</em> capability problem. Read why:</p>

<ul>
  <li><strong>It composes operations across at least two gateway surfaces.</strong> Even on the cleanest gateway (Kong), the flow is <code class="language-plaintext highlighter-rouge">POST consumers</code> → <code class="language-plaintext highlighter-rouge">POST consumer_groups</code> → <code class="language-plaintext highlighter-rouge">POST consumer_groups/{cgId}/consumers</code> → <code class="language-plaintext highlighter-rouge">POST consumers/{cid}/key-auth</code> → stream audit event. That’s five operations. On Apigee it’s four operations spread across two API surfaces (Management + Cloud Audit Logs). On AWS it’s three operations spread across three surfaces (API Gateway, IAM, CloudTrail).</li>
  <li><strong>The scope vocabulary is gateway-native and ugly.</strong> Kong has ACL plugin tags. Apigee has API Products. WSO2 has throttling policies. Tyk has <code class="language-plaintext highlighter-rouge">access_rights</code> arrays. The provider should declare scopes once in human-readable terms (<code class="language-plaintext highlighter-rouge">read:public</code>, <code class="language-plaintext highlighter-rouge">write:invoices</code>) and have the capability translate to whichever gateway-native primitive applies. That translation is exactly what Naftiko Capabilities are for.</li>
  <li><strong>The policy surface is declarative.</strong> Trusted issuers, auto-issuable scopes, approval channels, default rate limits, consent terms, audit destination. All YAML. Editable by the provider without touching the gateway. The capability enforces the policy on every onboarding request.</li>
  <li><strong>The outputs are multi-surface.</strong> The same capability publishes a REST endpoint (<code class="language-plaintext highlighter-rouge">POST /onboard</code>), an MCP tool (<code class="language-plaintext highlighter-rouge">agent.register</code>), and an agent skill (<code class="language-plaintext highlighter-rouge">onboard-agent.md</code>). One declaration, three derivative surfaces. That is the Naftiko Capabilities pattern exactly.</li>
</ul>

<p>The gateway team is unlikely to ship this for you. Kong is not going to write the adapter. Apigee is not going to write a Web Bot Auth verifier in Apigee’s policy language. WSO2 has <em>almost</em> shipped this in the form of dynamic client registration (<code class="language-plaintext highlighter-rouge">POST /register</code>), but they didn’t model agent identity and they didn’t ship the consent-hash or scope-translation legs of the flow. None of these vendors will. It is not their business model.</p>

<p>The vendor that ships it is the one that treats the flow as a portable capability that runs in front of any of them.</p>

<h2 id="what-the-capability-actually-contains">What the Capability Actually Contains</h2>

<p>An agent-onboarding Naftiko Capability declares roughly the following — note this is an illustrative sketch of the shape, simplified for the post. The first real artifact, against Kong Enterprise Admin, is committed at <a href="https://github.com/api-evangelist/kong/blob/main/capabilities/kong-agent-onboarding.yaml">api-evangelist/kong/capabilities/kong-agent-onboarding.yaml</a> and uses the canonical <code class="language-plaintext highlighter-rouge">naftiko: 1.0.0-alpha2</code> schema with <code class="language-plaintext highlighter-rouge">consumes</code> + <code class="language-plaintext highlighter-rouge">orchestration</code> + <code class="language-plaintext highlighter-rouge">exposes</code> sections per the <a href="https://github.com/naftiko/ikanos.wiki">Ikanos specification</a>.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">naftiko</span><span class="pi">:</span> <span class="s">1.0.0-alpha2</span>
<span class="na">info</span><span class="pi">:</span>
  <span class="na">label</span><span class="pi">:</span> <span class="s">Agent Onboarding (gateway-templated)</span>
  <span class="na">description</span><span class="pi">:</span> <span class="s">Verify agent identity, check policy, compose gateway operations,</span>
    <span class="s">return a scoped credential, emit audit. Valid against the canonical</span>
    <span class="s">naftiko 1.0.0-alpha2 schema; the Kong and AWS reference artifacts use</span>
    <span class="s">this exact shape.</span>
  <span class="na">tags</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">Agent Onboarding</span><span class="pi">,</span> <span class="nv">Web Bot Auth</span><span class="pi">,</span> <span class="nv">RFC 9421</span><span class="pi">]</span>
<span class="na">binds</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">namespace</span><span class="pi">:</span> <span class="s">env</span>
  <span class="na">keys</span><span class="pi">:</span>
    <span class="na">GATEWAY_ADMIN_TOKEN</span><span class="pi">:</span> <span class="s">GATEWAY_ADMIN_TOKEN</span>
    <span class="na">AGENT_TRUSTED_ISSUERS</span><span class="pi">:</span> <span class="s">AGENT_TRUSTED_ISSUERS</span>
    <span class="na">AGENT_CONSENT_HASH</span><span class="pi">:</span> <span class="s">AGENT_CONSENT_HASH</span>
<span class="na">capability</span><span class="pi">:</span>
  <span class="na">consumes</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">type</span><span class="pi">:</span> <span class="s">http</span>
    <span class="na">namespace</span><span class="pi">:</span> <span class="s">gateway-admin</span>
    <span class="na">baseUri</span><span class="pi">:</span> <span class="s1">'</span><span class="s">'</span>
    <span class="na">description</span><span class="pi">:</span> <span class="s">The 3-5 gateway-native operations the orchestration composes.</span>
    <span class="na">resources</span><span class="pi">:</span>
    <span class="c1"># See per-gateway artifacts for exact resource paths — Kong uses</span>
    <span class="c1"># /{workspace}/consumers + /{workspace}/consumer_groups + key-auth;</span>
    <span class="c1"># AWS uses /apikeys + /usageplans + /usageplans/{id}/keys; etc.</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">identity</span>
      <span class="na">path</span><span class="pi">:</span> <span class="s">/{gateway-native-identity-path}</span>
      <span class="na">operations</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">createidentity</span><span class="pi">,</span> <span class="nv">method</span><span class="pi">:</span> <span class="nv">POST</span> <span class="pi">}</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">scope-tier</span>
      <span class="na">path</span><span class="pi">:</span> <span class="s">/{gateway-native-scope-path}</span>
      <span class="na">operations</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">ensurescopetier</span><span class="pi">,</span> <span class="nv">method</span><span class="pi">:</span> <span class="nv">POST</span> <span class="pi">}</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">credential</span>
      <span class="na">path</span><span class="pi">:</span> <span class="s">/{gateway-native-credential-path}</span>
      <span class="na">operations</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">mintcredential</span><span class="pi">,</span> <span class="nv">method</span><span class="pi">:</span> <span class="nv">POST</span> <span class="pi">}</span>
    <span class="na">authentication</span><span class="pi">:</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">apikey</span>
      <span class="na">key</span><span class="pi">:</span> <span class="s">Authorization</span>
      <span class="na">value</span><span class="pi">:</span> <span class="s1">'</span><span class="s">'</span>
      <span class="na">placement</span><span class="pi">:</span> <span class="s">header</span>
  <span class="na">orchestration</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">onboard-agent</span>
    <span class="na">description</span><span class="pi">:</span> <span class="s">End-to-end agent onboarding — 7 steps from signature to credential.</span>
    <span class="na">inputs</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">signature</span><span class="pi">,</span> <span class="nv">type</span><span class="pi">:</span> <span class="nv">object</span><span class="pi">,</span> <span class="nv">required</span><span class="pi">:</span> <span class="nv">true</span> <span class="pi">}</span>
    <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">signature_agent</span><span class="pi">,</span> <span class="nv">type</span><span class="pi">:</span> <span class="nv">string</span><span class="pi">,</span> <span class="nv">required</span><span class="pi">:</span> <span class="nv">true</span> <span class="pi">}</span>
    <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">skill_id</span><span class="pi">,</span> <span class="nv">type</span><span class="pi">:</span> <span class="nv">string</span><span class="pi">,</span> <span class="nv">required</span><span class="pi">:</span> <span class="nv">true</span> <span class="pi">}</span>
    <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">requested_scopes</span><span class="pi">,</span> <span class="nv">type</span><span class="pi">:</span> <span class="nv">array</span><span class="pi">,</span> <span class="nv">required</span><span class="pi">:</span> <span class="nv">true</span> <span class="pi">}</span>
    <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">consent_hash</span><span class="pi">,</span> <span class="nv">type</span><span class="pi">:</span> <span class="nv">string</span><span class="pi">,</span> <span class="nv">required</span><span class="pi">:</span> <span class="nv">true</span> <span class="pi">}</span>
    <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">contact</span><span class="pi">,</span> <span class="nv">type</span><span class="pi">:</span> <span class="nv">object</span><span class="pi">,</span> <span class="nv">required</span><span class="pi">:</span> <span class="nv">true</span> <span class="pi">}</span>
    <span class="na">steps</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">verify_identity</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">builtin.web-bot-auth.verify</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">signature</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${input.signature}'</span>
        <span class="na">agent</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${input.signature_agent}'</span>
        <span class="na">trusted_issuers</span><span class="pi">:</span> <span class="s1">'</span><span class="s">'</span>
      <span class="na">on_failure</span><span class="pi">:</span> <span class="s">deny</span>
    <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">verify_consent</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">builtin.policy.assert</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">assert</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${input.consent_hash}</span><span class="nv"> </span><span class="s">==</span><span class="nv"> </span><span class="s">'</span>
      <span class="na">on_failure</span><span class="pi">:</span> <span class="s">deny</span>
    <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">classify_scopes</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">builtin.policy.scope-classify</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">requested</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${input.requested_scopes}'</span>
    <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">create_identity</span>
      <span class="na">call</span><span class="pi">:</span> <span class="s">gateway-admin.createidentity</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">body</span><span class="pi">:</span>
          <span class="na">agent_id</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.verify_identity.agent_id}'</span>
    <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">ensure_scope_tier</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">builtin.upsert</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">name</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.classify_scopes.target}'</span>
    <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">mint_credential</span>
      <span class="na">call</span><span class="pi">:</span> <span class="s">gateway-admin.mintcredential</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">identity_id</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.create_identity.id}'</span>
        <span class="na">scope_tier</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.ensure_scope_tier.id}'</span>
    <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">emit_audit</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">builtin.audit.emit</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">event</span><span class="pi">:</span> <span class="s">agent.onboarded</span>
        <span class="na">agent_id</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.verify_identity.agent_id}'</span>
        <span class="na">credential_id</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.mint_credential.id}'</span>
    <span class="na">output</span><span class="pi">:</span>
      <span class="na">agent_id</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.verify_identity.agent_id}'</span>
      <span class="na">credential</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.mint_credential.value}'</span>
      <span class="na">scope</span><span class="pi">:</span> <span class="s1">'</span><span class="s">${steps.classify_scopes.target}'</span>
  <span class="na">exposes</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">type</span><span class="pi">:</span> <span class="s">rest</span>
    <span class="na">namespace</span><span class="pi">:</span> <span class="s">agent-onboarding-rest</span>
    <span class="na">port</span><span class="pi">:</span> <span class="m">8080</span>
    <span class="na">resources</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">path</span><span class="pi">:</span> <span class="s">/v1/agents/onboard</span>
      <span class="na">operations</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="pi">{</span> <span class="nv">method</span><span class="pi">:</span> <span class="nv">POST</span><span class="pi">,</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">onboardagent</span><span class="pi">,</span> <span class="nv">call</span><span class="pi">:</span> <span class="nv">orchestration.onboard-agent</span> <span class="pi">}</span>
  <span class="pi">-</span> <span class="na">type</span><span class="pi">:</span> <span class="s">mcp</span>
    <span class="na">namespace</span><span class="pi">:</span> <span class="s">agent-onboarding-mcp</span>
    <span class="na">port</span><span class="pi">:</span> <span class="m">9090</span>
    <span class="na">transport</span><span class="pi">:</span> <span class="s">http</span>
    <span class="na">tools</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">agent-register</span><span class="pi">,</span> <span class="nv">call</span><span class="pi">:</span> <span class="nv">orchestration.onboard-agent</span> <span class="pi">}</span>
  <span class="pi">-</span> <span class="na">type</span><span class="pi">:</span> <span class="s">agent-skill</span>
    <span class="na">namespace</span><span class="pi">:</span> <span class="s">agent-onboarding-skill</span>
    <span class="na">skill</span><span class="pi">:</span> <span class="pi">{</span> <span class="nv">name</span><span class="pi">:</span> <span class="nv">onboard-agent</span><span class="pi">,</span> <span class="nv">file</span><span class="pi">:</span> <span class="nv">skills/onboard-agent.md</span> <span class="pi">}</span>
</code></pre></div></div>

<p>The runtime policy levers (require Web Bot Auth signature, require matching consent hash, deny forbidden scopes, defer approval-required scopes to a webhook) are <em>already encoded</em> in the orchestration steps via <code class="language-plaintext highlighter-rouge">on_failure: deny</code> — there is no separate <code class="language-plaintext highlighter-rouge">governance:</code> capability section to author. Policy enforcement is <em>what the orchestration is</em>.</p>

<p>The lint-time governance — the rules that say “any capability claiming to do agent onboarding MUST include verify_signature, verify_consent, classify_scopes, and emit_audit steps, MUST bind AGENT_TRUSTED_ISSUERS and AGENT_CONSENT_HASH in its env namespace, and MUST expose REST/MCP/agent-skill surfaces on the canonical paths” — lives in a Polychro ruleset, not in the capability YAML. Polychro is Naftiko’s <a href="https://github.com/naftiko/polychro.wiki">governance layer</a>, separate from the capability spec. The companion ruleset for this pattern is at <a href="https://github.com/api-evangelist/posts/blob/main/polychro/agent-onboarding-rules.yaml">api-evangelist/posts/polychro/agent-onboarding-rules.yaml</a> — 17 rules extending <code class="language-plaintext highlighter-rouge">polychro:ai-safety</code>, applied with <code class="language-plaintext highlighter-rouge">polychro lint --tags agent-onboarding</code>.</p>

<p>The three-layer split is the correct architecture per the canonical Naftiko docs: <strong>Ikanos</strong> is the capability spec (the YAML above), <strong>Polychro</strong> is the governance layer that lints capability files, and <strong>Naftiko Fleet</strong> is the operations layer that governs capabilities at scale across teams and compliance boundaries. None of those three is encoded inside the others.</p>

<p>The capability is a single artifact. It declares what the agent will send, what trust is required, which gateway operations get composed in which order, what the policy levers are, and which surfaces are produced. The Naftiko Framework runs it. The provider edits <code class="language-plaintext highlighter-rouge">policy.yaml</code> and re-deploys without ever touching the capability or the gateway. Ten reference artifacts are now committed across the API Evangelist GitHub organization, all valid <code class="language-plaintext highlighter-rouge">naftiko: 1.0.0-alpha2</code> against the canonical schema and all exposing the same three downstream surfaces — REST <code class="language-plaintext highlighter-rouge">POST /v1/agents/onboard</code>, MCP <code class="language-plaintext highlighter-rouge">agent-register</code> tool, and an agent skill at <code class="language-plaintext highlighter-rouge">/skills/onboard-agent.md</code> — so an agent that knows how to call the onboarding endpoint doesn’t care which capability sits behind it:</p>

<table>
  <thead>
    <tr>
      <th>Gateway</th>
      <th>Artifact</th>
      <th>Distinctive</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kong</td>
      <td><a href="https://github.com/api-evangelist/kong/blob/main/capabilities/kong-agent-onboarding.yaml">kong-agent-onboarding.yaml</a></td>
      <td>Single-surface adapter, 13 native MCP control-plane ops, Event Gateway for audit</td>
    </tr>
    <tr>
      <td>AWS API Gateway</td>
      <td><a href="https://github.com/api-evangelist/aws-api-gateway/blob/main/capabilities/aws-api-gateway-agent-onboarding.yaml">aws-api-gateway-agent-onboarding.yaml</a></td>
      <td>Dual identity verification (IAM principals + Web Bot Auth), CloudWatch + CloudTrail audit, usage-plan-bind-window invariant</td>
    </tr>
    <tr>
      <td>Apigee</td>
      <td><a href="https://github.com/api-evangelist/apigee/blob/main/capabilities/apigee-agent-onboarding.yaml">apigee-agent-onboarding.yaml</a></td>
      <td>Developer + App + API Product composition, Cloud Audit Logs side-channel</td>
    </tr>
    <tr>
      <td>WSO2</td>
      <td><a href="https://github.com/api-evangelist/wso2/blob/master/capabilities/wso2-agent-onboarding.yaml">wso2-agent-onboarding.yaml</a></td>
      <td>DCR-native (<code class="language-plaintext highlighter-rouge">POST /register</code>), per-API key model, native MCP server discovery via <code class="language-plaintext highlighter-rouge">getAllMCPServers</code></td>
    </tr>
    <tr>
      <td>Gravitee</td>
      <td><a href="https://github.com/api-evangelist/gravitee/blob/main/capabilities/gravitee-agent-onboarding.yaml">gravitee-agent-onboarding.yaml</a></td>
      <td>Plan-based scope (cleanest gateway-native abstraction), native audit on both APIM and AM</td>
    </tr>
    <tr>
      <td>Azure APIM</td>
      <td><a href="https://github.com/api-evangelist/microsoft-azure-api-management/blob/main/capabilities/azure-apim-agent-onboarding.yaml">azure-apim-agent-onboarding.yaml</a></td>
      <td>Product / Subscription / User nested scope, Microsoft Entra short-circuit for in-tenant agents, Azure Monitor audit</td>
    </tr>
    <tr>
      <td>Tyk</td>
      <td><a href="https://github.com/api-evangelist/tyk/blob/main/capabilities/tyk-agent-onboarding.yaml">tyk-agent-onboarding.yaml</a></td>
      <td>Shortest adapter in the field — <code class="language-plaintext highlighter-rouge">POST /tyk/keys</code> collapses identity + credential + scope + rate-limit + quota into one atomic call; GraphQL field-level scope via <code class="language-plaintext highlighter-rouge">restricted_types</code>; MDCB cross-region key sync</td>
    </tr>
    <tr>
      <td>Merge</td>
      <td><a href="https://github.com/api-evangelist/merge/blob/main/capabilities/merge-agent-onboarding.yaml">merge-agent-onboarding.yaml</a></td>
      <td>Meta-gateway pattern — one credential fans out to hundreds of downstream SaaS integrations via Linked Accounts</td>
    </tr>
    <tr>
      <td>Cloudflare</td>
      <td><a href="https://github.com/api-evangelist/cloudflare/blob/main/capabilities/cloudflare-agent-onboarding.yaml">cloudflare-agent-onboarding.yaml</a></td>
      <td>Edge-native — the worker IS the gateway; tokens minted at the edge, Workers KV trust cache, R2 + Logpush audit</td>
    </tr>
    <tr>
      <td>Deutsche Telekom / CAMARA</td>
      <td><a href="https://github.com/api-evangelist/deutsche-telekom/blob/main/capabilities/dt-camara-agent-onboarding.yaml">dt-camara-agent-onboarding.yaml</a></td>
      <td>Carrier-grade three-layer trust (operator agreement + agent registration + per-call user consent), regulatory archive with multi-year retention</td>
    </tr>
  </tbody>
</table>

<p>That’s ten gateway adapter shapes, all expressed as Naftiko Capabilities, all parsing with stock <code class="language-plaintext highlighter-rouge">yaml.safe_load</code>, all following the same <code class="language-plaintext highlighter-rouge">consumes</code> + <code class="language-plaintext highlighter-rouge">orchestration</code> + <code class="language-plaintext highlighter-rouge">exposes</code> structure documented in the canonical <a href="https://github.com/naftiko/ikanos.wiki">Ikanos capability spec</a>. The differences across the ten reflect the gateway data models and trust affordances — not the agent-facing contract. The orchestrations range from Tyk’s five-step minimum (one atomic gateway call) to Kong and Azure APIM’s eight-step composition; the shape of the contract above each of them is identical. The companion <a href="https://github.com/api-evangelist/posts/blob/main/polychro/agent-onboarding-rules.yaml">Polychro ruleset</a> lints every one of the ten artifacts for cross-capability consistency — same <code class="language-plaintext highlighter-rouge">verify_signature</code> / <code class="language-plaintext highlighter-rouge">verify_consent</code> / <code class="language-plaintext highlighter-rouge">classify_scopes</code> / <code class="language-plaintext highlighter-rouge">emit_audit</code> step contract, same REST/MCP/agent-skill exposed surfaces, same required env bindings.</p>

<p>The gateway-specific operation paths above are not invented — they are pulled directly from the OpenAPIs published across the <a href="https://github.com/api-evangelist">API Evangelist GitHub organization</a> at <a href="https://github.com/api-evangelist/kong/tree/main/openapi">api-evangelist/kong/openapi</a>, <a href="https://github.com/api-evangelist/apigee/tree/main/openapi">api-evangelist/apigee/openapi</a>, <a href="https://github.com/api-evangelist/wso2/tree/main/openapi">api-evangelist/wso2/openapi</a>, <a href="https://github.com/api-evangelist/tyk/tree/main/openapi">api-evangelist/tyk/openapi</a>, and the rest. I evaluated all of them this week and produced an inventory matrix scoring 75 gateway providers by how cleanly they can drive each leg of the flow.</p>

<p><img src="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/blue-circuit-docks-water-front.jpg" alt="Docks waterfront in the blue-circuit filter" /></p>

<h2 id="what-the-eval-surfaced">What the Eval Surfaced</h2>

<p>Four pieces of work behind this post — an adapter specification (the formal contract any per-gateway adapter must implement: <code class="language-plaintext highlighter-rouge">listAPIs</code>, <code class="language-plaintext highlighter-rouge">getSpec</code>, <code class="language-plaintext highlighter-rouge">issueCredential</code>, <code class="language-plaintext highlighter-rouge">streamAuditEvents</code>, <code class="language-plaintext highlighter-rouge">listMCPServers</code>), a Kong vs. Apigee deep dive (Kong’s adapter is ~4.5 days, Apigee’s is ~6.5 days plus a Cloud Audit Logs side-channel), a gateway inventory across 75 providers (Eight Tier-1 turnkey targets, thirty-three Tier-2 needing audit side-channels, thirty-four Tier-3 with thin OpenAPI surfaces), and the automated onboarding flow specification itself.</p>

<p>Three findings worth pulling out of that work:</p>

<p><strong>Three gateways already publish first-class MCP operations.</strong> WSO2 has seventy MCP-related operations in their Publisher and Devportal APIs, including <code class="language-plaintext highlighter-rouge">createMCPServerFromOpenAPI</code> and <code class="language-plaintext highlighter-rouge">createMCPServerFromAPI</code>. Workato has sixteen MCP-server-management operations including assigning tools to a server and renewing server tokens. Kong has thirteen MCP control-plane operations. Apigee, Tyk, Gravitee, AWS, and Google Cloud all have zero. The agent onboarding capability for those first three gateways doesn’t just <em>enable</em> MCP — it discovers and orchestrates MCP servers the gateway is already operating. That’s a meaningful value-add that no one is talking about.</p>

<p><strong>Audit observability is where the field splits.</strong> The Web Bot Auth signature that proves which agent registered needs to land somewhere the provider can later prove who-onboarded-whom. Kong, WSO2, and Gravitee ship native audit operations in their OpenAPI. Apigee, AWS, Google, and Azure push audit to their unified cloud audit log services — out of band from the gateway. The capability has to know how to talk to both shapes.</p>

<p><strong>The standardized package is two layers.</strong> A gateway-independent core (linkset emitter, robots.txt template, JSON-LD context, agent skill templates, the edge worker that injects RFC 8288 Link headers) sits on top of a per-gateway adapter (the operation-composition layer). The first half is approximately the <a href="https://apievangelist.com/2026/05/16/making-the-api-evangelist-network-agent-readable/">May 16 agent-readiness work</a> generalized. The second half is new per gateway.</p>

<h2 id="why-im-writing-this-up-without-shipping-it-yet">Why I’m Writing This Up Without Shipping It Yet</h2>

<p>I don’t have a live gateway tenant to run any of this against this spectrum. All ten capability artifacts are complete, schema-valid Naftiko Capability declarations, but none of them has yet been executed against a real customer environment. The full series of artifacts is design-validated — every YAML parses, every <code class="language-plaintext highlighter-rouge">consumes</code> block maps to operations the gateway actually publishes, every orchestration step references either a builtin or a consumed operation defined elsewhere in the same file — but the artifacts have not yet been deployed against any customer’s gateway tenant. I’m publishing the design before the implementation for three reasons.</p>

<p><strong>One:</strong> I am <a href="https://apievangelist.com/services">actively looking for design partners</a>. If you run an API program — at any scale — and the “we cannot onboard agents fast enough” problem is real for you, I would like to talk. Every major commercial API gateway in the field now has a committed reference capability; running any of them against a real customer tenant is one engagement away. The customer that goes first on any given gateway shapes the policy surface, the trust model, and the credential lifecycle to fit their needs while the standardized package is still being defined.</p>

<p><strong>Two:</strong> The design is more useful in public than in private. Every API gateway vendor I have talked to in the last two months is wrestling with some version of this question, and every API provider I have talked to is wrestling with the other side of it. Publishing the operation-by-operation map of how each major gateway’s existing API surface composes into this flow is a contribution to a conversation that needed somewhere to land. The conversation should not have to start over every time a provider gets asked “can your agent self-register against us.”</p>

<p><strong>Three:</strong> The work is the thing. I have been doing API Evangelist for fifteen years, and the pattern that has been most consistently true is that the design specs I publish early get implemented by people who needed exactly that design spec — sometimes by my customers, often by other vendors, occasionally as the eventual canonical version of the thing. The agent onboarding capability is a pattern that needs to exist. Whether I ship the reference implementation or whether someone else does, the capability shape above is what should ship. Writing it down clearly and pointing at the gateway operations that compose into it is the contribution worth making first.</p>

<h2 id="whats-updated">What’s Updated</h2>

<p>I have refreshed both my <a href="https://apievangelist.com/services">API Evangelist services page</a> and the <a href="https://apis.io/services/">APIs.io services page</a> to lead with the automated onboarding angle on the agentic-preparation service. The doorway pattern is still there — <code class="language-plaintext highlighter-rouge">.well-known/api-catalog</code>, <code class="language-plaintext highlighter-rouge">.well-known/mcp</code>, agent skills, secure credential issuance — but it now leads with the <em>automated</em> framing because that is what the work this week made clear is the actual differentiator. A doorway that requires a human at the gate is a portal. A doorway that recognizes a signed agent and provisions it in one round trip is a different thing.</p>

<p>If you are running an API program and your agents-need-credentials story is currently “they file a Jira ticket like everyone else,” let’s talk. Ten reference capabilities are committed across the <a href="https://github.com/api-evangelist">API Evangelist GitHub organization</a>, one per major gateway. The one that matches whichever gateway you operate is one engagement away from being executed against your tenant.</p>]]></content><author><name>Kin Lane</name></author><category term="Blog" /><category term="Agent Onboarding" /><category term="Naftiko Capabilities" /><category term="Naftiko Framework" /><category term="API Management" /><category term="API Gateways" /><category term="Agent Skills" /><category term="Web Bot Auth" /><category term="Dynamic Client Registration" /><category term="RFC 9421" /><category term="RFC 7591" /><summary type="html"><![CDATA[An agent shows up at your API. It has a verifiable identity, a clear purpose, and a list of scopes it would like. Your existing API management platform cannot give it credentials in one round trip — every gateway in the field still assumes a human developer behind a portal. The fix is not a new feature on your gateway. The fix is a Naftiko Capability that sits in front of the gateway you already have, composes the three or four calls needed to provision the agent, enforces the policy you declare, and returns a scoped credential. Here is what that capability looks like.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/copper-circuit-gatew-into-field.jpg" /><media:content medium="image" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/copper-circuit-gatew-into-field.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Where Is the Fortune 1000 at When It Coms to AI — Here Are the Receipts for All 989 of Them</title><link href="https://apievangelist.com/blog/2026/05/25/the-fortune-1000-is-saturated-with-ai/" rel="alternate" type="text/html" title="Where Is the Fortune 1000 at When It Coms to AI — Here Are the Receipts for All 989 of Them" /><published>2026-05-25T00:00:00+00:00</published><updated>2026-05-25T00:00:00+00:00</updated><id>https://apievangelist.com/blog/2026/05/25/the-fortune-1000-is-saturated-with-ai</id><content type="html" xml:base="https://apievangelist.com/blog/2026/05/25/the-fortune-1000-is-saturated-with-ai/"><![CDATA[<p>I now have the majority of Fortune 1000 profiled as part of API Evangelist, so I want to continue understanding where they are with AI. Similar to what I am doing with <a href="https://signals.naftiko.io">Naftiko Signals</a>, I want to understand the AI language being used by the Fortun 100.</p>

<p>This week I ran an experiment to make that claim concrete. For each of the 989 Fortune 1000 companies that I already have a repo for in the <a href="https://github.com/api-evangelist">API Evangelist GitHub Organization</a>, I pulled three things and stored them as markdown right next to the existing <code class="language-plaintext highlighter-rouge">apis.yml</code>:</p>

<ul>
  <li>The top five Google results for <code class="language-plaintext highlighter-rouge">"&lt;company&gt; artificial intelligence"</code>.</li>
  <li>The top five results for <code class="language-plaintext highlighter-rouge">"&lt;company&gt;" press release artificial intelligence</code>.</li>
  <li>The top five results for <code class="language-plaintext highlighter-rouge">"&lt;company&gt;" blog artificial intelligence</code>.</li>
</ul>

<p>Every artifact lands as a markdown file with YAML frontmatter (<code class="language-plaintext highlighter-rouge">title</code>, <code class="language-plaintext highlighter-rouge">url</code>, <code class="language-plaintext highlighter-rouge">date</code>, <code class="language-plaintext highlighter-rouge">query</code>, <code class="language-plaintext highlighter-rouge">position</code>, <code class="language-plaintext highlighter-rouge">source</code>). Then a second pass walks each company directory, counts mentions across a 35-term lexicon — <code class="language-plaintext highlighter-rouge">artificial intelligence</code>, <code class="language-plaintext highlighter-rouge">AI</code>, <code class="language-plaintext highlighter-rouge">machine learning</code>, <code class="language-plaintext highlighter-rouge">LLM</code>, <code class="language-plaintext highlighter-rouge">generative ai</code>, <code class="language-plaintext highlighter-rouge">foundation model</code>, <code class="language-plaintext highlighter-rouge">copilot</code>, <code class="language-plaintext highlighter-rouge">agentic</code>, <code class="language-plaintext highlighter-rouge">RAG</code>, <code class="language-plaintext highlighter-rouge">GPT-x</code>, <code class="language-plaintext highlighter-rouge">OpenAI</code>, <code class="language-plaintext highlighter-rouge">Anthropic</code>, <code class="language-plaintext highlighter-rouge">ChatGPT</code>, and a couple dozen more — and writes a per-company <code class="language-plaintext highlighter-rouge">AI-INVESTMENT.md</code> report. A final pass aggregates everything into a single rollup.</p>

<h2 id="the-numbers">The numbers</h2>

<ul>
  <li><strong>989</strong> Fortune 1000 companies have a repo and a full report.</li>
  <li><strong>44,025</strong> AI-term mentions across all the pulled markdown.</li>
  <li><strong>19,609</strong> of those are the exact string <code class="language-plaintext highlighter-rouge">artificial intelligence</code>.</li>
  <li><strong>44.5</strong> AI-term mentions per company on average.</li>
  <li><strong>0</strong> companies with zero AI signal across all pulled markdown.</li>
</ul>

<p>That last number is the headline. Even the Fortune 1000 companies you wouldn’t expect — Universal (the tobacco company at rank #854), Pep Boys at #850, Pinnacle Entertainment at #976 — produced at least one Google result mentioning AI somewhere in the snippet. The question of “is your industry talking about AI yet” is closed. Yes. All talking about it. The question is, what are they doing about it, and that reflects the work I am doing with <a href="https://signals.naftiko.io">Naftiko Signals</a>.</p>

<h2 id="three-lenses-three-different-leaderboards">Three lenses, three different leaderboards</h2>

<p>The first lens is raw mention count. It looks like this:</p>

<table>
  <thead>
    <tr>
      <th>Rank</th>
      <th>Company</th>
      <th>F1000</th>
      <th style="text-align: right">AI total</th>
      <th style="text-align: right"><code class="language-plaintext highlighter-rouge">artificial intelligence</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>American Express</td>
      <td>#88</td>
      <td style="text-align: right">327</td>
      <td style="text-align: right">20</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Hanover Insurance Group</td>
      <td>#511</td>
      <td style="text-align: right">321</td>
      <td style="text-align: right">34</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Teradata</td>
      <td>#809</td>
      <td style="text-align: right">217</td>
      <td style="text-align: right">20</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Juniper Networks</td>
      <td>#557</td>
      <td style="text-align: right">166</td>
      <td style="text-align: right">16</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Apache</td>
      <td>#218</td>
      <td style="text-align: right">161</td>
      <td style="text-align: right">16</td>
    </tr>
    <tr>
      <td>6</td>
      <td>Autodesk</td>
      <td>#862</td>
      <td style="text-align: right">119</td>
      <td style="text-align: right">21</td>
    </tr>
    <tr>
      <td>7</td>
      <td>Cisco Systems</td>
      <td>#60</td>
      <td style="text-align: right">115</td>
      <td style="text-align: right">31</td>
    </tr>
    <tr>
      <td>8</td>
      <td>Netflix</td>
      <td>#474</td>
      <td style="text-align: right">114</td>
      <td style="text-align: right">18</td>
    </tr>
    <tr>
      <td>9</td>
      <td>Leidos Holdings</td>
      <td>#506</td>
      <td style="text-align: right">113</td>
      <td style="text-align: right">32</td>
    </tr>
    <tr>
      <td>10</td>
      <td>Citrix Systems</td>
      <td>#725</td>
      <td style="text-align: right">109</td>
      <td style="text-align: right">18</td>
    </tr>
  </tbody>
</table>

<p>If you stop reading after this table you will draw the wrong conclusions. American Express and Hanover Insurance lead because they happened <em>not</em> to expose an RSS feed on their corporate homepage. That means their data is entirely the 15 search engine snippets I asked for — and those snippets are 100% AI-themed by query design. Microsoft, sitting at #31 in the same ranking with 90 mentions, did expose a feed. So Microsoft also has twenty broad blog posts in the sample, most of them not about AI, which drags the raw mention count down.</p>

<p>This is sample-size bias, not signal. To correct for it I added a second lens: <code class="language-plaintext highlighter-rouge">AI / item</code>, the average number of AI hits per pulled markdown file. Companies with fewer than ten items don’t qualify. The picture flips:</p>

<table>
  <thead>
    <tr>
      <th>Rank</th>
      <th>Company</th>
      <th style="text-align: right">AI / item</th>
      <th style="text-align: right">Items pulled</th>
      <th style="text-align: right">% items w/ AI</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Hanover Insurance Group</td>
      <td style="text-align: right">12.8</td>
      <td style="text-align: right">25</td>
      <td style="text-align: right">80%</td>
    </tr>
    <tr>
      <td>2</td>
      <td>American Express</td>
      <td style="text-align: right">11.7</td>
      <td style="text-align: right">28</td>
      <td style="text-align: right">86%</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Mattel</td>
      <td style="text-align: right">5.9</td>
      <td style="text-align: right">15</td>
      <td style="text-align: right">100%</td>
    </tr>
    <tr>
      <td>4</td>
      <td>CDW</td>
      <td style="text-align: right">5.4</td>
      <td style="text-align: right">15</td>
      <td style="text-align: right">100%</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Juniper Networks</td>
      <td style="text-align: right">5.4</td>
      <td style="text-align: right">31</td>
      <td style="text-align: right">94%</td>
    </tr>
    <tr>
      <td>6</td>
      <td>Verizon</td>
      <td style="text-align: right">5.3</td>
      <td style="text-align: right">15</td>
      <td style="text-align: right">100%</td>
    </tr>
    <tr>
      <td>7</td>
      <td>AT&amp;T</td>
      <td style="text-align: right">5.3</td>
      <td style="text-align: right">15</td>
      <td style="text-align: right">100%</td>
    </tr>
    <tr>
      <td>8</td>
      <td>Citigroup</td>
      <td style="text-align: right">5.2</td>
      <td style="text-align: right">15</td>
      <td style="text-align: right">100%</td>
    </tr>
    <tr>
      <td>9</td>
      <td>Baker Hughes</td>
      <td style="text-align: right">5.2</td>
      <td style="text-align: right">15</td>
      <td style="text-align: right">100%</td>
    </tr>
    <tr>
      <td>10</td>
      <td>Visa</td>
      <td style="text-align: right">5.1</td>
      <td style="text-align: right">15</td>
      <td style="text-align: right">100%</td>
    </tr>
  </tbody>
</table>

<p>Hanover and Amex stay on top because their <em>broader</em> RSS-discovered items also happened to mention AI — twenty of twenty-five blog posts, twenty-four of twenty-eight, respectively. That is genuine density, not selection.</p>

<p>The third lens is the one I find most useful: how many of the items in a company’s <code class="language-plaintext highlighter-rouge">press/</code> directory actually mention AI. Press releases are the most authoritative channel — those are the things the company chose to put its own logo on. This leaderboard is different again:</p>

<table>
  <thead>
    <tr>
      <th>Rank</th>
      <th>Company</th>
      <th style="text-align: right">Press items w/ AI</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Teradata</td>
      <td style="text-align: right">20</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Alphabet</td>
      <td style="text-align: right">13</td>
    </tr>
    <tr>
      <td>3</td>
      <td>salesforce.com</td>
      <td style="text-align: right">12</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Coca-Cola</td>
      <td style="text-align: right">10</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Time Warner</td>
      <td style="text-align: right">10</td>
    </tr>
    <tr>
      <td>6</td>
      <td>Blackstone Group</td>
      <td style="text-align: right">8</td>
    </tr>
    <tr>
      <td>7</td>
      <td>VF</td>
      <td style="text-align: right">8</td>
    </tr>
    <tr>
      <td>8</td>
      <td>CommScope Holding</td>
      <td style="text-align: right">7</td>
    </tr>
    <tr>
      <td>9</td>
      <td>NCR</td>
      <td style="text-align: right">7</td>
    </tr>
    <tr>
      <td>10</td>
      <td>Union Pacific</td>
      <td style="text-align: right">6</td>
    </tr>
  </tbody>
</table>

<p>Notice how Alphabet barely registers in the raw count (#29) but jumps to #2 here because their press feed surfaced thirteen distinct AI announcements. Union Pacific shows up at #10 — a railroad, in a list otherwise full of software and finance. That is worth a look.</p>

<h2 id="industry-density">Industry density</h2>

<p>Aggregating by industry and dividing by company count gives a cleaner read on which sectors are <em>uniformly</em> engaged with AI versus which have a few loud companies and a long quiet tail:</p>

<table>
  <thead>
    <tr>
      <th>Industry</th>
      <th style="text-align: right">Companies</th>
      <th style="text-align: right">Avg AI mentions / company</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Computer Software</td>
      <td style="text-align: right">13</td>
      <td style="text-align: right">81.2</td>
    </tr>
    <tr>
      <td>Network and Other Communications Equipment</td>
      <td style="text-align: right">14</td>
      <td style="text-align: right">68.1</td>
    </tr>
    <tr>
      <td>Commercial Banks</td>
      <td style="text-align: right">25</td>
      <td style="text-align: right">64.6</td>
    </tr>
    <tr>
      <td>Information Technology Services</td>
      <td style="text-align: right">11</td>
      <td style="text-align: right">62.3</td>
    </tr>
    <tr>
      <td>Internet Services and Retailing</td>
      <td style="text-align: right">13</td>
      <td style="text-align: right">56.2</td>
    </tr>
    <tr>
      <td>Insurance: Property and Casualty</td>
      <td style="text-align: right">28</td>
      <td style="text-align: right">54.5</td>
    </tr>
    <tr>
      <td>Diversified Financials</td>
      <td style="text-align: right">14</td>
      <td style="text-align: right">54.7</td>
    </tr>
    <tr>
      <td>Diversified Outsourcing Services</td>
      <td style="text-align: right">14</td>
      <td style="text-align: right">53.3</td>
    </tr>
    <tr>
      <td>Telecommunications</td>
      <td style="text-align: right">16</td>
      <td style="text-align: right">50.8</td>
    </tr>
    <tr>
      <td>Pharmaceuticals</td>
      <td style="text-align: right">15</td>
      <td style="text-align: right">50.8</td>
    </tr>
  </tbody>
</table>

<p>Software and networking lead, which surprises no one. Banks and insurance at #3 and #6 are the interesting story — financial services has gone from “AI is interesting” to “AI is part of the press cadence” faster than I would have predicted three years ago.</p>

<h2 id="the-methodology">The methodology</h2>

<p>Some caveats, because I am not going to pretend this is a clean academic measurement:</p>

<ul>
  <li><strong>The lexicon is permissive.</strong> <code class="language-plaintext highlighter-rouge">\bAI\b</code> matches any standalone “AI” — and most of the time that is what we want, but in a press release that lists a product code like “AI-204” it will overcount. I accept this tradeoff. The point is to find which companies are <em>talking</em> about AI a lot, not to write a definition of AI.</li>
  <li><strong>RSS coverage is patchy.</strong> Of 989 companies, only <strong>197</strong> exposed a discoverable RSS feed for blogs or press from their corporate homepage. The rest have no machine-readable channel for their own announcements. The remaining 792 companies are visible to this analysis only through search engines view. That is a real story about how few Fortune 1000 companies bother to publish a feed in 2026, separate from this analysis.</li>
</ul>

<h2 id="what-im-taking-away">What I’m taking away</h2>

<p>Three things.</p>

<p><strong>The first</strong> is that “is your industry doing AI” is the wrong question now. The signal floor is non-zero across every industry in the Fortune 1000, including the ones I expected to come up empty. Mining. Tobacco. Specialty retail. All of them have public AI mentions findable in three search engine queries.</p>

<p><strong>The second</strong> is that the interesting differentiation is not raw volume but channel and density. Alphabet putting thirteen AI announcements through its press feed is a different signal than American Express having a lot of AI articles written <em>about</em> it. Both matter. They are not the same thing.</p>

<p><strong>The third</strong> is that this entire pipeline took an afternoon to build, ran in under an hour of API time, and produced 989 company reports plus a ranked rollup as markdown that I can grep, version, and link to. That is the version of “AI investment analysis” I want to do: build it once, run it everywhere, store the receipts as plain markdown next to the rest of the company’s API and capability data, and let the index be the artifact.</p>

<p>Honestly I don’t know what any of this means. It all feels like noise. I will be doing the diff with the signals I’ve been gathering as part of my Naftiko work. Search engines, blogs, press releases for the Fortune 1000 spin one narrative, the job postings and GitHub repos (if they have) tell another. I think the jobs are the leading indicator for whether it is all talk or if there is any actual investment. Also, with the job postings I don’t think it is just about hiring for AI terms, and is about hiring for data, pipelines, APIs, and all the things that will determine if you are successful.</p>]]></content><author><name>Kin Lane</name></author><category term="Blog" /><category term="Artificial Intelligence" /><category term="Fortune 1000" /><category term="SerpAPI" /><category term="API Evangelist Network" /><category term="Naftiko" /><category term="Signals" /><category term="Press Releases" /><summary type="html"><![CDATA[I pulled blog posts, press releases, and the top five Google results for every Fortune 1000 company that has a repo in my network — 989 of them — and counted AI mentions. The result is 44,025 hits across a 35-term lexicon. Zero companies score zero. The interesting question is no longer who is talking about AI; it is who has anything to say underneath the talk.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/eugenics-times-square-up-road.jpg" /><media:content medium="image" url="https://kinlane-productions2.s3.amazonaws.com/algorotoscope-master/eugenics-times-square-up-road.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Only Four API Providers Publish a Real .well-known/api-catalog Right Now</title><link href="https://apievangelist.com/blog/2026/05/22/four-providers-publishing-well-known-api-catalog/" rel="alternate" type="text/html" title="Only Four API Providers Publish a Real .well-known/api-catalog Right Now" /><published>2026-05-22T00:00:00+00:00</published><updated>2026-05-22T00:00:00+00:00</updated><id>https://apievangelist.com/blog/2026/05/22/four-providers-publishing-well-known-api-catalog</id><content type="html" xml:base="https://apievangelist.com/blog/2026/05/22/four-providers-publishing-well-known-api-catalog/"><![CDATA[<p>RFC 9727 has been a published IETF standard for over a year. It defines <code class="language-plaintext highlighter-rouge">/.well-known/api-catalog</code> as the machine entrypoint for discovering an organization’s APIs — a small, boring, eminently useful primitive. An agent (or a developer, or a tool) does a GET against that path, gets back an <code class="language-plaintext highlighter-rouge">application/linkset+json</code> document, and finds the URLs of every OpenAPI, AsyncAPI, or other spec the provider publishes. No HTML crawl. No “the docs are over here, the spec is over there”. One known place, one machine-readable answer.</p>

<p>I have been writing about this pattern for the better part of two years. I added <code class="language-plaintext highlighter-rouge">well-known-catalog</code> as a forward-looking dimension in the <a href="https://github.com/api-evangelist/agent-readiness">agent-readiness model</a> I shipped this week. And I noticed yesterday, while writing up <a href="https://github.com/api-evangelist/merge">Merge.dev’s pipeline refresh</a>, that Merge had quietly added one — ten entries, one per Unified API category, with the OpenAPI YAML on each typed link. That made me wonder how many other providers I’d missed.</p>

<p>So I ran a probe. Seventy-four providers — every company in the recent round of API Evangelist pipeline refreshes (the embedded iPaaS players, the identity providers, the cloud gateways, the docs platforms, the SDK generators, the agent infrastructure companies, the observability vendors) plus the obvious large surfaces that should have one if anyone does (Stripe, Twilio, GitHub, Salesforce, Microsoft Graph, Google, Postman, Plaid, Slack, Shopify, every API gateway). Six URL candidates per provider — bare domain, <code class="language-plaintext highlighter-rouge">docs.</code>, <code class="language-plaintext highlighter-rouge">developer.</code>, <code class="language-plaintext highlighter-rouge">developers.</code>, <code class="language-plaintext highlighter-rouge">api.</code>, <code class="language-plaintext highlighter-rouge">platform.</code>. Five hundred and eighteen HTTPS requests, fired in parallel.</p>

<h2 id="the-answer-is-four">The answer is four</h2>

<p>Four providers serve a real RFC 9727 LinkSet at <code class="language-plaintext highlighter-rouge">/.well-known/api-catalog</code>:</p>

<table>
  <thead>
    <tr>
      <th>Provider</th>
      <th>Endpoint</th>
      <th>Entries</th>
      <th>Notable</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Cloudflare</strong></td>
      <td><a href="https://developers.cloudflare.com/.well-known/api-catalog"><code class="language-plaintext highlighter-rouge">developers.cloudflare.com/.well-known/api-catalog</code></a></td>
      <td>1</td>
      <td>Returns <code class="language-plaintext highlighter-rouge">application/linkset+json; profile="https://www.rfc-editor.org/info/rfc9727"</code>. Points at the bundled <code class="language-plaintext highlighter-rouge">openapi.json</code>. Three different host prefixes all resolve to the same content.</td>
    </tr>
    <tr>
      <td><strong>Memesio</strong></td>
      <td><a href="https://memesio.com/.well-known/api-catalog"><code class="language-plaintext highlighter-rouge">memesio.com/.well-known/api-catalog</code></a></td>
      <td>2</td>
      <td>The only catalog I observed that publishes <strong>both</strong> the REST API and the MCP server endpoint as separate linkset entries. The template the other three should copy.</td>
    </tr>
    <tr>
      <td><strong>Merge.dev</strong></td>
      <td><a href="https://docs.merge.dev/.well-known/api-catalog"><code class="language-plaintext highlighter-rouge">docs.merge.dev/.well-known/api-catalog</code></a></td>
      <td>10</td>
      <td>The deepest catalog — one entry per Unified API category (HRIS, ATS, Accounting, CRM, Ticketing, File Storage, plus the newer ones). Each entry points at a category-specific OpenAPI YAML. The model for how a multi-product provider should structure their catalog.</td>
    </tr>
    <tr>
      <td><strong>Zuplo</strong></td>
      <td><a href="https://zuplo.com/.well-known/api-catalog"><code class="language-plaintext highlighter-rouge">zuplo.com/.well-known/api-catalog</code></a></td>
      <td>1</td>
      <td>The only catalog whose typed link explicitly declares the OpenAPI version (<code class="language-plaintext highlighter-rouge">application/vnd.oai.openapi+json;version=3.1</code>). A gateway company practicing what they preach.</td>
    </tr>
  </tbody>
</table>

<p>That is the entire field as of today. Four out of seventy-four.</p>

<p>Two providers returned a clean 404. Sixty-eight returned <code class="language-plaintext highlighter-rouge">200 OK</code> — but the body was HTML. They were single-page-app catch-all routes serving the homepage from the well-known path. An agent following the standard would get a 200, try to parse a LinkSet out of the body, fail, and have no useful recourse. That is worse than a 404. A 404 tells the agent the resource doesn’t exist; an HTML 200 at a well-known path lies.</p>

<h2 id="the-four-are-not-who-i-expected">The four are not who I expected</h2>

<p>I expected Stripe to have one. They don’t.</p>

<p>I expected Twilio to have one. They don’t.</p>

<p>I expected at least one of the big docs platforms — ReadMe, Mintlify, Bump.sh, Redocly, Stoplight — to have one for their own site, given that publishing developer-facing infrastructure is the entire business. None of them do.</p>

<p>I expected every API gateway in the field to have one as a credibility signal. Of the seven I probed — Kong, Tyk, Apigee, Apache APISIX, Gravitee, KrakenD, WSO2 — none do. Only Zuplo. Cloudflare does it on the docs site, which is the closest the hyperscaler gateways get.</p>

<p>I expected, frankly, that any of the agent infrastructure companies — Composio, Toolhouse, Smithery, Letta, Arcade, Jentic, Naftiko — would have one as their literal job description. None do.</p>

<p>What I got instead was a CDN/edge company, a small startup most people have never heard of, a unified-API company, and a developer-first gateway company. The shape of the field that has actually implemented this is not the shape of the field that talks about agent readiness.</p>

<h2 id="what-good-looks-like">What good looks like</h2>

<p>The Memesio catalog is the one I’d point any provider at as a template. It is two lines:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"linkset"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w"> </span><span class="nl">"anchor"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://memesio.com/api"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"service-desc"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="nl">"href"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://memesio.com/api/openapi"</span><span class="p">,</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"application/json"</span><span class="p">}]</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="p">{</span><span class="w"> </span><span class="nl">"anchor"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://memesio.com/api/mcp"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"service-desc"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="nl">"href"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://memesio.com/api/mcp"</span><span class="p">,</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"application/json"</span><span class="p">}]</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>That is the entire payload an agent needs to discover both the REST API and the MCP server. It costs you a single static file behind a CDN. It costs you nothing to maintain. It is the smallest, cheapest, most boring agent-readiness commitment you can make as a provider — and it makes the difference between an agent that finds your API in one round-trip and an agent that has to crawl your blog.</p>

<p>The Merge catalog is the second template — the multi-product version. If you ship one product, you can fit the whole story in one entry like Cloudflare or Zuplo. If you ship a family of APIs like Merge does (or like Stripe does, or Twilio, or Salesforce), one entry per product line is the move. You do not have to pick which to advertise. You advertise all of them.</p>

<h2 id="what-the-gap-means">What the gap means</h2>

<p>The gap is not a standards-maturity gap. RFC 9727 has been published for over a year. It builds on RFC 9264 LinkSet, which itself was published in 2022. The IETF httpapi WG has been clear about the design.</p>

<p>The gap is a <strong>prioritisation gap</strong>. Every provider I named above ships agent-themed product launches, AI gateway integrations, MCP servers, “Auth for AI” press releases. The smallest possible agent-readiness primitive — one well-known path that returns a tiny JSON document pointing at the OpenAPI you already publish — is the thing they have skipped. It’s the API-publishing equivalent of selling a beautiful house without putting up a number on the mailbox.</p>

<p>I’m going to start using this as one of the first signals I check when I write up a provider. If you ship a <code class="language-plaintext highlighter-rouge">/.well-known/api-catalog</code> you’re telling me you’ve thought about agents finding your API by themselves. If you don’t, you’re telling me you’ve thought about agents using your API only after a human has already onboarded them. Those are two different products.</p>

<p>If you work at a provider with a public API, your TODO is one PR. Add a <code class="language-plaintext highlighter-rouge">linkset</code> JSON file. Serve it with <code class="language-plaintext highlighter-rouge">Content-Type: application/linkset+json; profile="https://www.rfc-editor.org/info/rfc9727"</code>. Point it at the OpenAPI you already publish — and at your MCP server if you have one. That’s the whole task. You will join Cloudflare, Memesio, Merge.dev, and Zuplo on the very short list of providers an agent can actually find without me writing a custom crawler.</p>

<p>The signal records for all four observed catalogs are committed in the <a href="https://github.com/api-evangelist/agent-readiness">api-evangelist/agent-readiness</a> topic repo, scored as exemplary against the <code class="language-plaintext highlighter-rouge">well-known-catalog</code> dimension. I’ll re-run the probe next quarter. I’d like the table to be longer.</p>]]></content><author><name>Kin Lane</name></author><category term="Blog" /><category term="Agent Readiness" /><category term="RFC 9727" /><category term="API Discovery" /><category term=".well-known" /><category term="Linkset" /><category term="OpenAPI" /><category term="MCP" /><summary type="html"><![CDATA[I probed 74 likely-candidate API providers — the recent API Evangelist pipeline batch plus the obvious large surfaces — for a real RFC 9727 LinkSet at `/.well-known/api-catalog`. Four serve one. Sixty-eight serve a 200 OK that turns out to be a single-page-app catch-all. Two return a clean 404.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://s3.amazonaws.com/kinlane-productions2/api-evangelist-logos/api-evangelist-butterfly-vertical.png" /><media:content medium="image" url="https://s3.amazonaws.com/kinlane-productions2/api-evangelist-logos/api-evangelist-butterfly-vertical.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>