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: *.
| Feed | What it covers | How it is gathered |
|---|---|---|
[api-health.json](api-health.json) | free, no-auth public data APIs | measured — one read-only GET per API, every day |
[ai-deals.json](ai-deals.json) | free and trial offers from AI providers | documented — read off the provider's own page on a stated date |
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 measured — evidence 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.
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.
api-health.json:
| Field | Meaning |
|---|---|
generated_at | when the sweep that produced this file ran (UTC, ISO 8601) |
counts | totals by status for this run |
results | one object per checked API |
ai-deals.json:
| Field | Meaning |
|---|---|
schema | feed format identifier |
vertical | subject area of the catalog |
generated_at | when this file was generated (UTC, ISO 8601) |
curated_at | when the catalog was originally researched — older than generated_at, and deliberately so |
transferred_at, transferred_by | when the catalog was handed to this project, and by whom |
provenance | how the rows were gathered |
staleness_warning | computed at build time from the rows; names its denominator |
counts | totals by offer status |
items | one 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| Field | Meaning |
|---|---|
name | the API's name |
category | Developer, Finance, Geo, Health, Knowledge, News, Weather |
auth | what the endpoint requires — none for the no-auth set |
check_url | the exact URL probed; one small idempotent GET |
status | OK, AUTH, HTTP_ERR, or DOWN |
http | HTTP status code returned, if the request completed |
latency_ms | round-trip time in milliseconds |
content_type | Content-Type as returned |
body_snippet | first few hundred characters of the response, emails redacted |
ai-deals.json — item fields| Field | Meaning |
|---|---|
id | stable identifier for the row |
name, provider, category | what the offer is and who runs it |
offer_status | available, 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_what | what is actually free, in the provider's terms. null on every negative |
finding | on a negative row, what was checked and not found |
access | what the call needs: api-key, oauth, phone-verification, credit-card |
acquisition | what you need to get in: none, api-signup, web-form, oauth-only, phone-verify, payment-card |
acquisition_evidence | probed if the signup page was fetched and read; documented if derived from access |
acquisition_probed_at | when it was probed, where it was |
acquisition_source | the page the gate was read from |
agent_usable | can a running agent consume this via API once a human has cleared the barrier |
evidence | documented throughout — see above |
confidence | how firm the row is |
source_url | the provider page the claim comes from |
verified_at | the date that claim was read. This is the field to compute freshness from |
caveats | anything that qualifies the offer |
observations | real calls made by other workers, attributed, never first-party |
access and acquisition are separate fieldsThey 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.
source_url and verified_at is a rumour, not a resource, anddoes not ship. This is enforced at build time and applies to negatives exactly as it does to offers.
measured without a matching first-party call recorded inthis project. The validation workflow fails the run otherwise.
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.
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.
Generated with the feeds themselves, so this section cannot drift from what is actually served.
api-health.json | ai-deals.json | |
|---|---|---|
| Rows | 35 | 47 |
| Generated | 2026-08-23T18:22:20Z | 2026-08-23T18:22:20Z |
| Gathered by | daily measurement | provider documentation |
Staleness of ai-deals.json — 39 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.