API Docs Finder - OpenAPI/Swagger Spec, llms.txt & Docs URLs avatar

API Docs Finder - OpenAPI/Swagger Spec, llms.txt & Docs URLs

Pricing

from $3.85 / 1,000 domain locateds

Go to Apify Store
API Docs Finder - OpenAPI/Swagger Spec, llms.txt & Docs URLs

API Docs Finder - OpenAPI/Swagger Spec, llms.txt & Docs URLs

For AI agents about to call an unfamiliar API: give a company domain, get its OpenAPI/Swagger spec (version, endpoints, auth), llms.txt, docs, API reference, status page, changelog, official npm/PyPI SDKs and GraphQL endpoint, each URL verified. On 42 API companies: llms.txt found for 35.

Pricing

from $3.85 / 1,000 domain locateds

Rating

0.0

(0)

Developer

NeverEmpty

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

23 days ago

Last modified

Share

Give your AI agent a company domain and get back where that company's developer resources live, each URL verified: the OpenAPI/Swagger spec (downloaded and read: spec version, API version, endpoint count, auth types, servers), llms.txt and llms-full.txt, the developer docs home, the API reference, the status page (and its current status when allowed), the changelog (and the RSS/Atom feed it declares), the official npm and PyPI SDK packages with the evidence that they are official, and whether a GraphQL endpoint answers. One call, one row per domain, with a one-sentence summary the agent can read as is.

Only verified resources are returned as found: the URL answered 2xx and the content has the expected shape (a JSON/YAML file with an openapi or swagger version, a Markdown llms.txt rather than an HTML page, a docs page whose title or place says so). Links it could not verify (too large, over your download limit, behind a wall) are listed separately in notVerified with the reason. Every place it tried is listed in searched with what it answered, so "not found" comes with the list of places that were checked.

Example

Input:

{ "domains": ["stripe.com"] }

Output (production run pJMr2xEKNHE4SKcBg, shortened):

{
"domain": "stripe.com",
"summary": "stripe.com: OpenAPI 3.0.0 spec \"Stripe API\" version 2026-09-30.endive (612 operations, auth: http basic, http bearer) at https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json; llms.txt at https://stripe.com/llms.txt; docs at https://docs.stripe.com/; API reference at https://docs.stripe.com/api; status page at https://status.stripe.com/; changelog at https://stripe.com/blog/changelog; npm: stripe@22.6.2, @stripe/extensibility-sdk@3.0.0, @stripe/ui-extension-sdk@9.3.0; PyPI: stripe 15.6.1. Not found: GraphQL endpoint.",
"found": ["openapi", "llms", "docs", "apiReference", "status", "changelog", "sdks"],
"missing": ["graphql"],
"openapiUrl": "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json",
"openapiSpecVersion": "3.0.0",
"apiVersion": "2026-09-30.endive",
"endpointCount": 612,
"authTypes": ["http basic", "http bearer"],
"llmsTxtUrl": "https://stripe.com/llms.txt",
"docsUrl": "https://docs.stripe.com/",
"apiReferenceUrl": "https://docs.stripe.com/api",
"statusPageUrl": "https://status.stripe.com/",
"statusPageProvider": "custom",
"changelogUrl": "https://stripe.com/blog/changelog",
"npmPackages": [{ "name": "stripe", "latestVersion": "22.6.2", "evidence": "it is published or maintained by an @stripe.com account" }],
"pypiPackages": [{ "name": "stripe", "latestStableVersion": "15.6.1", "evidence": "its releases are published with the author e-mail @stripe.com" }],
"searchedCount": 60
}

With no input at all it searches stripe.com, so the Actor always returns a row.

What it finds, per domain

found valueHow it is foundHow it is verified
openapiWell-known paths on api., the site and docs hosts (/openapi.json, /openapi.yaml, /swagger.json, /.well-known/openapi.json, /v3/api-docs and more), spec links on the home page, docs pages and in llms.txt, and the free APIs.guru catalog (original source first, then its mirror copy)Downloaded (up to 20 MB) and parsed as JSON or YAML; must carry openapi: 3.x or swagger: 2.0. You get spec version, title, API version, path and operation counts, auth types from the security schemes, server URLs, and publishedBy (company-domain, company-github, apis-guru-mirror or third-party)
llms/llms.txt on the site and docs hosts, then llms-full.txt next to itMust be Markdown, not HTML, and not a redirect to another page. You get its H1 title, the > summary, the ## section names and the link count
docsdocs., developer., developers., platform. hosts, /docs, /developers, and docs links on the home pageA real HTML page (not the home page, not a soft 404) whose title says docs/developers/reference, or that sits on a docs host or path
apiReference/api, /reference, /api-reference on the docs hosts, and API reference links from the docs and llms.txtTitle says API reference/REST API/reference, or it sits on a docs host with such a path
statusstatus.<domain>, <brand>status.com, and status links on the siteThe page is a status page (Atlassian Statuspage, incident.io, Instatus, Better Stack, Status.io and others); for Statuspage, /api/v2/status.json is read for currentStatus only when robots.txt allows it
changelog/changelog, /docs/changelog, /release-notes on the site and docs hosts, and changelog linksTitle or path says changelog/release notes/what's new. The RSS/Atom feed the page declares is returned as changelogFeedUrl as declared (not fetched)
sdksnpm registry search for the brand name, PyPI release feeds for the likely package namesnpm: the package's homepage/repository points to the domain, or it is published or maintained by an account at the domain, or its GitHub org is linked from the company's own pages. PyPI: the release feed's author e-mail is at the domain. Platform-only binary packages are left out
graphqlapi.<domain>/graphql, /graphql, /api/graphqlA GET answer only a GraphQL server gives ("Must provide query string", an errors list with locations/extensions, a 401 pointing to GraphQL docs) or a GraphiQL/Playground page. Nothing is queried; authRequired shows a 401/403 answer

Measured

One production run on 42 well-known API companies (Stripe, GitHub, Slack, OpenAI, Anthropic, Apify, Shopify, Twilio, Notion, Resend, Supabase, Vercel, Linear, Clerk, HubSpot, Cloudflare, Sentry, Airtable, Mailchimp, Render, Postmark, Zapier, Discord, Dropbox, SendGrid, Spotify, Atlassian, GitLab, DigitalOcean, PagerDuty, Datadog, Algolia, Mapbox, PayPal, Plaid, Zoom, Figma, freee, SmartHR, Chatwork, Asana, PAY.JP), default settings, 540 seconds (run XcCnurPxU1fUmbJux):

founddomains
developer docs42 of 42
official SDK packages40
status page38
llms.txt35
API reference30
changelog29
OpenAPI/Swagger spec (downloaded and read)23
GraphQL endpoint1

4,371 requests, 378 of them robots.txt; 312 URLs were not requested because robots.txt disallows them. A single domain takes about 8 seconds (stripe.com: 67 requests, including its 8 MB spec). Checked against a browser on three production runs (spec version, title and API version; llms.txt title; docs, status, changelog and API reference pages; npm latest version): 60 of 62 checks agreed, and the other 2 were limits of the checking script (an 11.6 MB spec the browser could not hold, and an llms.txt whose first line is not a heading, which this Actor correctly reports as having no title).

Input

FieldDefaultWhat it does
domains(example stripe.com)Domains, 1 to 100 per run. URLs and subdomains are read as their domain (https://docs.stripe.com/api = stripe.com); the same domain twice is searched and charged once.
includeallAny of openapi, llms, docs, apiReference, status, changelog, sdks, graphql. Fewer means a faster run; the price per domain is the same.
verifySpecs3How many linked or catalog-listed spec files are downloaded and read per domain (0 to 10). Specs at well-known paths are always read.
onlyChangesfalseMonitor mode: return only domains where something changed since the last run with the same watchName.
watchNameName of the remembered state for monitor mode.
resetMonitoringStatefalseForget the remembered state before this run.
maxConcurrency3Domains searched in parallel (1 to 5). Each site gets at most 3 requests at a time.
requestTimeoutSecs20Time limit per request (5 to 60 s); spec downloads get up to 45 s. Each domain gets at most 120 s in total.

Output columns

status (ok, nothing-found, unreachable, bad-input, budget-reached, no-change), domain, input, summary, found, missing, openapiUrl, openapiTitle, openapiSpecVersion, apiVersion, endpointCount, authTypes, openapiSpecs (each: url, foundVia, publishedBy, format, specVersion, title, apiVersion, pathCount, operationCount, authTypes, serverUrls, sizeBytes, apisGuruKey, description), llmsTxtUrl, llmsFullTxtUrl, llmsTxt (each: url, title, summary, sections, linkCount, sizeBytes, followsSpec), docsUrl, docs, apiReferenceUrl, statusPageUrl, statusPageProvider, currentStatus, statusJsonUrl, changelogUrl, changelogFeedUrl, changelogs, npmPackages and pypiPackages (each with name, latestVersion, url, evidence), graphqlUrl, graphql (url, httpStatus, evidence, authRequired), githubOrgsLinked, notVerified (kind, url, why), skippedByRobots, timeLimitReached, searchedCount, searched (kind, url, result), monitor columns (changeType, changedFields, previous, previousCheckedAt, watchName), note, checkedAt.

Monitor mode

Set watchName and onlyChanges: true and schedule the run. The first run returns every domain. Later runs return only domains where something changed: a spec added or removed, a new API version or endpoint count, new llms.txt sections, a new docs, status or changelog URL, or a new SDK release, with changedFields and the previous values. A resource that could not be read this time (timeout, 5xx, 429, a challenge page) is never reported as removed; it is compared again on the next run.

Pricing

Pay per event:

  • Domain located: each domain where at least one resource was verified.
  • Domain re-checked (monitor mode only): each domain that was searched and compared but had no change, so no row was returned.
  • Run start: once per run that returned or re-checked at least one domain.

Free: domains where nothing could be verified (the row lists every place tried), domains that do not resolve, invalid input, and the rows that say a run hit its maximum total charge. A run whose maximum total charge cannot fit the start fee plus one domain searches nothing and costs nothing.

Use it from an AI agent (MCP)

Through the Apify MCP server the input can be just {"domains": ["example.com"]}. Read summary first; use openapiUrl to load the spec, llmsTxtUrl to load the model-friendly docs, and statusPageUrl/currentStatus to check an outage before blaming your own code.

Limits and rules it follows

  • It reads a URL only when that site's robots.txt allows it (ApiDocsFinder, otherwise User-agent: *, RFC 9309 with prefix matching). URLs it skipped for that reason are listed in skippedByRobots. A robots.txt that answers 5xx or not at all means that host is treated as disallowed.
  • It never signs in, never solves or bypasses a challenge page or CAPTCHA, and does not spoof browser fingerprints. It uses the Actor's own server, no proxy.
  • pypi.org project pages answer with a JavaScript check, so PyPI packages are read from their public release feeds (/rss/project/<name>/releases.xml) instead; the npm registry search and APIs.guru are public APIs.
  • Domains are searched in parallel (default 3) and each domain gets at most 120 seconds; places not tried in time are listed in searched as skipped-time-limit and the row says timeLimitReached.
  • It finds what a company publishes on its own domain, subdomains and linked GitHub orgs. Docs on a separate domain that nothing links to (for example a product-branded developer site) may be missed; they then do not appear in found.
  • Two-level country suffixes such as co.jp, co.uk, com.pl and gov.au are read as suffixes (allegro.com.pl is searched as allegro.com.pl); a bare suffix such as com.pl is refused as input.
  • Not affiliated with any of the companies named here.

Support

Open an issue on the Issues tab with the domain and the run ID.