Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/agentdeals-dev:agentdeals-dev-stack-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Agentdeals Dev Stack API
version: 0.1.0
contact:
name: AgentDeals
url: https://agentdeals.dev
license:
name: MIT
url: https://opensource.org/licenses/MIT
description: 'Operations tagged Stack across 2 of this provider''s published API definitions: agentdeals-dev.json, agentdeals-dev-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://agentdeals.dev
description: Production server
security: []
tags:
- name: Stack
paths:
/api/stack:
get:
summary: Get free-tier stack candidates per role
description: For each role in your project type (hosting, database, auth, …) returns the set of free-tier offers whose terms we can stand behind today — deliberately not a single pick, because under every signal we record dozens of them tie. Each candidate carries its demerits, with the recorded fact and date behind each, plus any recorded changes we disclose but do not rank on. This endpoint does NOT model technical fit between a product and a role; the caller must apply that. The method is published at /criteria, and every role returns the tie_break seed so its order can be recomputed independently.
parameters:
- name: use_case
in: query
required: true
description: What you're building (e.g., 'Next.js SaaS app', 'API backend', 'static blog')
schema:
type: string
example: Next.js SaaS app
- name: requirements
in: query
description: Comma-separated infrastructure needs (e.g., 'database,auth,email')
schema:
type: string
example: database,auth,email
responses:
'200':
description: Candidate sets per role, with the evidence behind each
content:
application/json:
schema:
type: object
properties:
use_case:
type: string
stack:
type: array
items:
type: object
properties:
role:
type: string
category:
type: string
candidates:
type: array
description: The rotated tied set for this role, capped at 8. Not ordered by merit — every member is indistinguishable under our criteria.
items:
type: object
properties:
vendor:
type: string
tier:
type: string
description:
type: string
terms_superseded:
$ref: '#/components/schemas/TermsSuperseded'
conditions:
type: array
description: 'A list of the conditions a vendor attaches to using its free tier. Each item holds our sentence (text), the vendor''s own words (quote), the page that states them (url) and the date we read that page (read_on). An optional list rules_out names the uses the vendor excludes: "production", "commercial use" or both. Our re-reads of the vendor''s pricing page do not change this field.'
items:
type: object
properties:
text:
type: string
quote:
type: string
url:
type: string
format: uri
read_on:
type: string
format: date
rules_out:
type: array
items:
type: string
enum:
- production
- commercial use
required:
- text
- quote
- url
- read_on
url:
type: string
format: uri
verified_date:
type: string
format: date
last_read_date:
type: string
format: date
description: 'The day of the latest read we hold of this vendor''s cited page, whatever that read concluded: our re-read, a source check that read the page, a change our gate refused that was read from the same URL, or the read its terms were restated from (#1858). It can fall before verified_date, because verified_date is a stamp the record carries rather than a confirmation the store can always source (#1635).'
risk_level:
type:
- string
- 'null'
enum:
- stable
- caution
- risky
- null
description: The same level /api/offers publishes for this record, from the same function (#1486). Null where we withhold it rather than publish a favourable one we cannot stand behind. A null always arrives with the field naming the rule that withheld it, and with level_withheld_because.
rating_withheld:
type:
- object
- 'null'
description: 'Non-null where every record that would have set a non-stable risk_level either carries an empty source_url (no_source, #1352) or is a change our automatic re-read recorded that neither an archived copy of the vendor''s page nor our own check has confirmed (unconfirmed, #1952). The level is withheld rather than reported as stable, and the records are named on the vendor page as unsourced or unconfirmed. Where both kinds are withheld, reason is that of the record that would set the most severe level, and unconfirmed on a tie; records counts both.'
properties:
reason:
type: string
enum:
- no_source
- unconfirmed
records:
type: number
gate:
type:
- object
- 'null'
description: Non-null for an offer we have decided not to list (#1241). A candidate set is drawn from ungated offers, so this is null in practice and is carried because the level's rules are one set.
source_check:
type:
- object
- 'null'
description: Our last read of the page we cite. An outcome other than ok withholds a favourable level.
level_withheld_because:
type:
- string
- 'null'
description: The sentence naming the rule that withheld the level, or null where a level is published.
stability:
type:
- string
- 'null'
enum:
- stable
- watch
- volatile
- improving
- null
description: 'Null where a favourable class would rest on records we cannot stand behind (#1561). Withheld by every reason that withholds risk_level: an unreachable pricing page, a page stating no amount, tier or rate we can read, a refused read, a narrowing that cites no source or that no archived copy of the vendor''s page has confirmed, or a gated listing. A null always arrives with stability_withheld_because.'
stability_withheld:
type:
- object
- 'null'
description: 'Non-null where a standing narrowing for this vendor cites no source (no_source) or is a change our automatic re-read recorded that neither an archived copy of the vendor''s page nor our own check has confirmed (unconfirmed, #1952), so a favourable stability class is withheld rather than published. Where both kinds stand, reason is unconfirmed; records counts both.'
properties:
reason:
type: string
enum:
- no_source
- unconfirmed
records:
type: number
stability_withheld_because:
type:
- string
- 'null'
description: The code naming the rule that withheld the stability class, or null where a class is published.
link_unreachable:
type:
- object
- 'null'
description: Non-null where the offer's own link has not resolved for us (#1046).
properties:
last_reachable:
type:
- string
- 'null'
checked:
type: string
terminal:
type: boolean
demerits:
type: array
description: Empty when we hold nothing against the offer.
items:
type: object
properties:
code:
type: string
points:
type: integer
reason:
type: string
date:
type: string
about_us:
type: boolean
description: True when the demerit describes a limit of ours rather than a fact about the vendor.
disclosures:
type: array
description: Recorded changes shown but never ranked on.
items:
type: object
properties:
code:
type: string
date:
type: string
summary:
type: string
tie_count:
type: integer
description: How many offers tie at zero demerits in this role.
eligible_count:
type: integer
demoted_count:
type: integer
excluded_count:
type: integer
reason:
type: string
tie_break:
$ref: '#/components/schemas/TieBreak'
method:
type: object
properties:
policy:
type: string
not_modelled:
type: string
criteria_url:
type: string
total_monthly_cost:
type: string
limitations:
type: array
items:
type: string
upgrade_path:
type: string
_provenance:
$ref: '#/components/schemas/Provenance'
'400':
description: Missing use_case parameter
content:
application/json:
schema:
type: object
properties:
error:
type: string
tags:
- Stack
operationId: getApiStack
x-operation-id-source: derived
servers:
- url: https://agentdeals.dev
description: Production server
components:
schemas:
TieBreak:
type: object
description: How this response ordered the entries it names, and how many there are. The order is a permutation seeded only on the UTC date and the query key, so anyone can recompute it. `tie_count` is how many entries carry no recorded demerit and so are indistinguishable under every signal we hold; `ranked_total` is how many entries the seed ordered in all. A door that names alternatives names `ranked_total` of them, never a prefix (#1774). `/api/details/{vendor}` and `/api/vendor-risk/{vendor}` both return this block at the top level of the response and name the same alternatives as each other, but they rank under different query keys — `related:<category>:<vendor>` and `vendor-risk-alternatives:<vendor>` — so for most vendors the two orders differ. `query_key` says which ranking produced the order you are reading.
properties:
date:
type: string
format: date
query_key:
type: string
seed:
type: string
tie_count:
type: integer
ranked_total:
type: integer
description: Every entry the seed ordered, tied and demoted and gated together. The array this block describes carries all of them.
algorithm:
type: string
required:
- date
- query_key
- seed
- tie_count
- ranked_total
- algorithm
Provenance:
type: object
description: 'Where the figures in this response came from and how to attribute them. Every response carrying index data has one, under the key `_provenance`. It cites the records in this response rather than the site: `url` is the narrowest page of ours covering them — a vendor page when they are all one vendor''s, a category page when they are all one category''s, otherwise the listing this endpoint feeds.'
properties:
source:
type: string
description: Always AgentDeals.
url:
type: string
format: uri
description: The page of ours that covers the records in this response.
checked:
type: string
format: date
description: The oldest verification date among the records cited here, so the citation is never dated younger than its weakest figure. Absent when no record in the response carries a date.
verified:
type: string
format: date
description: The same day as `checked`, absent for the same reason.
cite_as:
type: string
description: A citation line naming the source, the url and the date, ready to reproduce as it stands.
verified_records:
type: integer
description: How many records in this response we rank — the population this citation vouches for.
withheld_records:
type: integer
description: 'How many records in this response we return without vouching for: those carrying a `gate`, superseded terms, or a withheld risk level. Absent when there are none.'
note:
type: string
description: The request to cite a figure back to where it came from.
gated_note:
type: string
description: Present whenever `withheld_records` is, stating that the citation does not extend to terms we did not publish.
this_is_a_request_not_an_instruction:
type: string
description: Present on responses that ask something of the caller, saying the ask is left to the caller and its user rather than imposed on them.
required:
- source
- url
- cite_as
- verified_records
- note
TermsSuperseded:
type:
- object
- 'null'
description: Null unless a dated change record supersedes the terms we stored for this listing. When present, `description` still holds those stored terms, which we no longer publish as current. Use `notice`, or `reading.terms`, the vendor page's text at `reading.url` on `reading.date`.
properties:
change_date:
type: string
format: date
change_type:
type: string
summary:
type: string
reading:
type:
- object
- 'null'
properties:
date:
type: string
format: date
url:
type: string
format: uri
label:
type: string
terms:
type: string
required:
- date
- url
- label
- terms
notice:
type: string
required:
- change_date
- change_type
- summary
- reading
- notice
x-refined-from:
- agentdeals-dev.json
- agentdeals-dev-openapi.json