The JSON feeds

Free Tier Sentinel publishes two machine-readable feeds. They are free, need no key, no signup and no authentication, and are served over HTTPS with access-control-allow-origin: *.

FeedWhat it coversHow it is gathered
[api-health.json](api-health.json)free, no-auth public data APIsmeasured — one read-only GET per API, every day
[ai-deals.json](ai-deals.json)free and trial offers from AI providersdocumented — read off the provider's own page on a stated date

The distinction that matters most

The two feeds are gathered by different methods, and the difference is not a detail of implementation — it is what each one is worth.

api-health.json is measured. Every row is the result of an HTTP request this project actually made, on the day stamped in the feed. The status code and the latency are observations, not claims.

ai-deals.json is documented. Every row states what the provider's own page advertised on the date in verified_at. This project holds no credential for any of these providers and has not called their APIs, so no row in that feed is measuredevidence reads documented on every one of them. Where another worker has made a real call, it appears in observations, attributed to whoever made it, and never promoted to a first-party claim.

Do not treat the two as one dataset. A liveness probe and a documented offer are different kinds of statement, and averaging them produces something that is neither.

How fresh each one is

api-health.json is re-measured daily. Its generated_at is when the sweep ran.

ai-deals.json is not on a re-verification schedule. There is an alert that reports how stale it is, and no pass that refreshes it — building that is tracked as an open issue. The feed's staleness_warning is computed from the rows at build time and says exactly where the catalog stands; the current value appears below. Every row carries its own verified_at, so a consumer never has to take the aggregate on trust: recount it.

That is the honest position, and it is stated here rather than glossed. A catalog whose pitch is "checked and dated" has to publish the dates even when they are old — especially then.

Top-level fields

api-health.json:

FieldMeaning
generated_atwhen the sweep that produced this file ran (UTC, ISO 8601)
countstotals by status for this run
resultsone object per checked API

ai-deals.json:

FieldMeaning
schemafeed format identifier
verticalsubject area of the catalog
generated_atwhen this file was generated (UTC, ISO 8601)
curated_atwhen the catalog was originally researched — older than generated_at, and deliberately so
transferred_at, transferred_bywhen the catalog was handed to this project, and by whom
provenancehow the rows were gathered
staleness_warningcomputed at build time from the rows; names its denominator
countstotals by offer status
itemsone object per offer, including the negatives

generated_at and curated_at are not the same thing, and the difference has bitten a consumer. generated_at is when the file you are reading was produced. curated_at is when the underlying research was done. Compute freshness from the per-item verified_at, not from either of them.

api-health.json — result fields

FieldMeaning
namethe API's name
categoryDeveloper, Finance, Geo, Health, Knowledge, News, Weather
authwhat the endpoint requires — none for the no-auth set
check_urlthe exact URL probed; one small idempotent GET
statusOK, AUTH, HTTP_ERR, or DOWN
httpHTTP status code returned, if the request completed
latency_msround-trip time in milliseconds
content_typeContent-Type as returned
body_snippetfirst few hundred characters of the response, emails redacted

ai-deals.json — item fields

FieldMeaning
idstable identifier for the row
name, provider, categorywhat the offer is and who runs it
offer_statusavailable, retired, none, or unverified. Negatives live in the main array, not a sibling one — "this provider has no free tier" is a finding worth publishing
free_whatwhat is actually free, in the provider's terms. null on every negative
findingon a negative row, what was checked and not found
accesswhat the call needs: api-key, oauth, phone-verification, credit-card
acquisitionwhat you need to get in: none, api-signup, web-form, oauth-only, phone-verify, payment-card
acquisition_evidenceprobed if the signup page was fetched and read; documented if derived from access
acquisition_probed_atwhen it was probed, where it was
acquisition_sourcethe page the gate was read from
agent_usablecan a running agent consume this via API once a human has cleared the barrier
evidencedocumented throughout — see above
confidencehow firm the row is
source_urlthe provider page the claim comes from
verified_atthe date that claim was read. This is the field to compute freshness from
caveatsanything that qualifies the offer
observationsreal calls made by other workers, attributed, never first-party

Why access and acquisition are separate fields

They answer different questions and they come apart. Modal's row reads access: api-key — the API call takes a key — but the key itself sits behind an OAuth sign-in, so acquisition: oauth-only. An agent reading only access concludes it can obtain a credential unaided, and it cannot.

Coverage of acquisition is partial by design. The probe fetches the signup page and reads it, which works on server-rendered pages and comes back inconclusive on JavaScript consoles. acquisition_evidence tells you which kind of answer you are holding. A probe can reveal a stricter gate than recorded, but it can never rule out one that appears later in the flow.

Provenance rules

does not ship. This is enforced at build time and applies to negatives exactly as it does to offers.

this project. The validation workflow fails the run otherwise.

Reuse

The feeds are public and free to read, use and redistribute. No key, no quota, no registration. Attribution to Free Tier Sentinel is requested but not enforced.

If you are building on the data: prefer verified_at per row over any aggregate, and mirror rather than hammer — the whole file is small, and one fetch a day is plenty.

A formal licence has not yet been declared. That is an owner decision and is pending; until it is made, the paragraph above describes the intent rather than a legal grant.

Corrections

If a row is wrong, it is worth reporting: a free tier that has quietly changed is exactly what this project exists to catch, and a correction is more useful than a complaint. Both feeds carry source_url on every row so a claim can be checked against the provider directly.

In the feeds right now

Generated with the feeds themselves, so this section cannot drift from what is actually served.

api-health.jsonai-deals.json
Rows3547
Generated2026-08-23T18:22:20Z2026-08-23T18:22:20Z
Gathered bydaily measurementprovider documentation

Staleness of ai-deals.json39 of 41 available offers are older than 30 days; oldest 41 days, median 41. These rows state what the provider advertised when last checked, not what it advertises today.