AgentDeals Changes API

The Changes API from AgentDeals — 1 operation(s) for changes.

Operations 1

GET /api/changes Deal and pricing changes #

Work with this as data

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-changes-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 Specification

agentdeals-dev-changes-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Agentdeals Dev Changes API
  version: 0.1.0
  contact:
    name: AgentDeals
    url: https://agentdeals.dev
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  description: 'Operations tagged Changes 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: Changes
paths:
  /api/changes:
    get:
      summary: Deal and pricing changes
      description: Returns tracked pricing and tier changes across vendors. Filter by date, change type, vendor, or category. A tracked pricing change is a change a vendor made to published terms, which we recorded, still stands, and we have not withdrawn. Most carry the date the terms took effect; the rest carry the date we read the page. The rule and the four totals it separates are at /changes#what-counts, and every response carries them as change_census.
      parameters:
      - name: since
        in: query
        description: 'Only return changes dated on or after this date. Accepts a calendar date (YYYY-MM-DD) or an ISO-8601 timestamp, which is narrowed to the date it names — the whole of that day is returned either way. A date that does not exist answers 400. Default: 30 days ago, and only when no other filter is passed — a request carrying type, vendor, vendors, categories or category searches the whole change log unless since says otherwise. The filter compares against each record''s date. Where date_meaning is "effective", that is the day the change took effect; where it is "discovered", it is the day we recorded the change, and when it took effect is unknown. Every response states the window it applied under date_window.'
        schema:
          type: string
          format: date
        example: '2025-01-01'
      - name: type
        in: query
        description: Filter by change type. Every type a record can carry is accepted; the same list types the `change_type` field on the records that come back.
        schema:
          type: string
          enum:
          - free_tier_removed
          - open_source_killed
          - product_deprecated
          - limits_reduced
          - restriction
          - pricing_restructured
          - pricing_model_change
          - limits_increased
          - new_free_tier
          - new_tier
          - startup_program_expanded
          - pricing_postponed
          - rebranded
          - record_corrected
      - name: vendor
        in: query
        description: 'Filter by vendor name. Matched by case-insensitive substring, not by exact name: vendor=Pilot returns GitHub Copilot''s records and category=ai returns Email''s. Nothing is narrowed on your behalf, so read name_match, which every response carries: it names what this filter matched and whether each match was exact.'
        schema:
          type: string
      - name: vendors
        in: query
        description: 'Comma-separated vendor names to filter by (e.g. ''Vercel,Supabase,Clerk''). Matched by case-insensitive substring, not by exact name: vendor=Pilot returns GitHub Copilot''s records and category=ai returns Email''s. Nothing is narrowed on your behalf, so read name_match, which every response carries: it names what this filter matched and whether each match was exact.'
        schema:
          type: string
        example: Vercel,Supabase
      - name: category
        in: query
        description: 'Comma-separated category names to filter by (e.g. ''Database,Cloud Hosting''). Matched by case-insensitive substring, not by exact name: vendor=Pilot returns GitHub Copilot''s records and category=ai returns Email''s. Nothing is narrowed on your behalf, so read name_match, which every response carries: it names what this filter matched and whether each match was exact.'
        schema:
          type: string
        example: Database,Hosting
      - name: categories
        in: query
        description: 'Comma-separated category names to filter by (e.g. ''Database,Cloud Hosting''). Matched by case-insensitive substring, not by exact name: vendor=Pilot returns GitHub Copilot''s records and category=ai returns Email''s. Nothing is narrowed on your behalf, so read name_match, which every response carries: it names what this filter matched and whether each match was exact.'
        schema:
          type: string
        example: Database,Hosting
      - name: limit
        in: query
        description: Max results per page
        schema:
          type: integer
          default: 20
      - name: offset
        in: query
        description: Number of results to skip
        schema:
          type: integer
          default: 0
      - name: include_retracted
        in: query
        description: Records we have withdrawn as our own error (standing 'retracted') are left out unless you ask for them. Set true to receive them alongside the rest; they arrive carrying standing 'retracted' and impact 'none'. Either way, retracted_excluded reports how many your query matched and did not receive. Anything other than 'true' or 'false' answers 400 rather than being ignored.
        schema:
          type: boolean
          default: false
      - name: include_index_housekeeping
        in: query
        description: Records of our own index housekeeping (reports 'our_index') are left out unless you ask for them. They say we stopped listing an offer of ours, not that the vendor changed anything, so counting them as vendor activity overstates it. Set true to receive them alongside the rest. Either way, index_housekeeping_excluded reports how many your query matched and did not receive. Anything other than 'true' or 'false' answers 400 rather than being ignored.
        schema:
          type: boolean
          default: false
      responses:
        '200':
          description: List of deal changes
          content:
            application/json:
              schema:
                type: object
                properties:
                  changes:
                    type: array
                    items:
                      $ref: '#/components/schemas/PublishedDealChange'
                  total:
                    type: integer
                    description: Records matching your query before paging, counting only the ones served. Retracted records are outside this count unless include_retracted is true, and our own index housekeeping is outside it unless include_index_housekeeping is true. Measured over the same population as all_time_total, so a type-filtered total and the whole-log figure can be compared.
                  returned:
                    type: integer
                  limit:
                    type: integer
                  offset:
                    type: integer
                  include_retracted:
                    type: boolean
                    description: The value this response was built with, echoed back.
                  retracted_excluded:
                    type: integer
                    description: How many records matched your query and were withheld for carrying standing 'retracted'. Zero when include_retracted is true, because nothing was withheld. Read this before comparing a count against an earlier one.
                  include_index_housekeeping:
                    type: boolean
                    description: The value this response was built with, echoed back.
                  index_housekeeping_excluded:
                    type: integer
                    description: How many records matched your query and were withheld for carrying reports 'our_index'. Zero when include_index_housekeeping is true, because nothing was withheld. Read this before comparing a count against an earlier one.
                  date_window:
                    $ref: '#/components/schemas/ChangeDateWindow'
                  advisory:
                    type: array
                    items:
                      $ref: '#/components/schemas/PublishedDealChange'
                    description: Top 3 high-impact changes outside your filter, drawn from the last 30 days whatever date_window says — this block is what is worth knowing lately, so it stays recent even when your query searches the whole log. Never contains a retracted record, whatever include_retracted says.
                  summary:
                    type: object
                    properties:
                      stack_changes_count:
                        type: integer
                      ecosystem_high_impact_count:
                        type: integer
                      period_days:
                        type: integer
                  all_time_total:
                    type: integer
                    description: The whole change log measured by the published rule, unaffected by your query. Equal to change_census.tracked_pricing_changes. A tracked pricing change is a change a vendor made to published terms, which we recorded, still stands, and we have not withdrawn. Most carry the date the terms took effect; the rest carry the date we read the page.
                  change_census:
                    type: object
                    description: Every total we publish is one of these four and names which. A tracked pricing change is a change a vendor made to published terms, which we recorded, still stands, and we have not withdrawn. Most carry the date the terms took effect; the rest carry the date we read the page. The rule is at /changes#what-counts.
                    properties:
                      tracked_pricing_changes:
                        type: integer
                        description: tracked pricing changes. A tracked pricing change is a change a vendor made to published terms, which we recorded, still stands, and we have not withdrawn. Most carry the date the terms took effect; the rest carry the date we read the page.
                      changes_still_in_force:
                        type: integer
                        description: 'changes still in force. Adds our own bookkeeping: corrections we made to our own records, each dated the day we made it, and index housekeeping — a source we dropped, written up as the vendor deprecating a product.'
                      records_we_stand_behind:
                        type: integer
                        description: records we stand behind. Adds changes the vendor has since reversed. They happened; they no longer hold.
                      records_held:
                        type: integer
                        description: records in the change log. Adds records we withdrew as our own error. They describe events that did not happen.
                      retrievable_from_this_door:
                        type: integer
                        description: How many records this request could return before paging. Follows include_retracted and include_index_housekeeping, so it is the only figure here that your query moves.
                      rule_url:
                        type: string
                        format: uri
                      note:
                        type: string
                  _provenance:
                    $ref: '#/components/schemas/Provenance'
              example:
                changes:
                - vendor: Heroku
                  change_type: free_tier_removed
                  date: '2022-11-28'
                  summary: Heroku eliminated all free dynos, free Postgres, and free Redis.
                  previous_state: Free dyno (550-1000 hrs/mo), free Postgres (10K rows), free Redis (25MB)
                  current_state: 'No free tier. Cheapest plan: $5/mo Eco dyno.'
                  impact: high
                  source_url: https://blog.heroku.com/next-chapter
                  category: Cloud Hosting
                  alternatives:
                  - Railway
                  - Render
                  - Fly.io
                total: 1
                returned: 1
                limit: 20
                offset: 0
        '400':
          description: Invalid since parameter
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
      tags:
      - Changes
      operationId: getApiChanges
      x-operation-id-source: derived
    servers:
    - url: https://agentdeals.dev
      description: Production server
components:
  schemas:
    ChangeDateWindow:
      type: object
      description: The date filter this response was built under, stated whether or not one ran. A count of 0 means we hold no matching record only when applied is false; when applied is true it means we hold none dated on or after from, and the same query with a wider since may answer differently. The default 30-day window runs on the unfiltered feed alone — a request naming a type, vendor, vendors or category is answered from the whole change log.
      properties:
        applied:
          type: boolean
          description: Whether any date filter narrowed this response.
        from:
          type:
          - string
          - 'null'
          format: date
          description: The earliest date a record could carry and still be returned. Null when applied is false.
        source:
          type: string
          enum:
          - default
          - since_parameter
          - none
          description: '''since_parameter'' — your since value. ''default'' — our window, because the request named no filter. ''none'' — no date filter ran.'
        field:
          type: string
          enum:
          - date
          description: The record field from compares against. date is the effective date only where date_meaning is "effective"; where it is "discovered", date is the day we recorded the change; where it is "effective_by", date is the latest day the change can have taken effect.
        note:
          type: string
          description: The same statement in prose, for a caller reading the response rather than parsing it.
      required:
      - applied
      - from
      - source
      - field
      - note
    DealChange:
      type: object
      properties:
        vendor:
          type: string
        change_type:
          type: string
          enum:
          - free_tier_removed
          - open_source_killed
          - product_deprecated
          - limits_reduced
          - restriction
          - pricing_restructured
          - pricing_model_change
          - limits_increased
          - new_free_tier
          - new_tier
          - startup_program_expanded
          - pricing_postponed
          - rebranded
          - record_corrected
        reports:
          type: string
          enum:
          - vendor_offer
          - our_index
          description: What the record is about. 'vendor_offer' — the vendor changed its own offer, and a vendor page is where that can be read. 'our_index' — we changed what we list while the vendor's offer stood still, so no vendor page evidences it and the record carries no source_url. Absent means vendor_offer. Filter these out of any figure you present as vendor market activity.
        date:
          type: string
          format: date
        summary:
          type: string
        previous_state:
          type: string
        current_state:
          type: string
        tier_direction:
          type: string
          enum:
          - narrowed
          - unchanged
          - widened
          description: Whether the tier we list is worse, the same, or better under current_state than it was under previous_state, judged with both in hand rather than read off change_type. Where it says the tier did not get worse we publish the record and take no risk verdict from it. Absent means we have not judged this record.
        impact:
          type: string
          enum:
          - high
          - medium
          - low
        source_url:
          type: string
          format: uri
        category:
          type: string
        alternatives:
          type: array
          items:
            type: string
        resolution:
          $ref: '#/components/schemas/ChangeResolution'
      required:
      - vendor
      - change_type
      - date
      - summary
      - previous_state
      - current_state
      - impact
      - source_url
      - category
      - alternatives
    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
    PublishedDealChange:
      allOf:
      - $ref: '#/components/schemas/DealChange'
      - type: object
        properties:
          standing:
            type: string
            enum:
            - in_force
            - reversed
            - retracted
            description: 'Where the record stands with us. ''in_force'' — the change happened and still holds. ''reversed'' — it happened and has since been undone, so the record is true history. ''retracted'' — the record was our error and we do not stand behind it. Read this rather than testing whether resolution is present: ''reversed'' and ''retracted'' are different answers to a reader asking whether to trust the record, and the presence of resolution flattens them into one.'
          impact:
            type: string
            enum:
            - high
            - medium
            - low
            - none
            description: '''none'' whenever standing is ''retracted'' — a record we have withdrawn describes no event, so it weighs nothing. Derived at the point of serving; the stored value is left alone.'
          date_meaning:
            type: string
            enum:
            - effective
            - discovered
            - effective_by
            description: 'What this record''s date means. "effective": the day the change took effect. "discovered": the day we recorded the change; when it took effect is unknown. "effective_by": the latest day the change can have taken effect. Where archived copies of the vendor''s page bracket a change, it is dated by the first copy that shows the new terms. Read this field, not date_source: date_source says who wrote the record, not what its date means.'
          ends_a_free_tier:
            type: boolean
          listing_effect:
            type: string
            enum:
            - ends
            - narrows
            - none
          archive_check:
            type:
            - object
            - 'null'
            description: 'Our check of this record against archived copies of the vendor''s page (#1952). Absent where we have not checked the record. Only the outcome no_usable_capture changes how the record counts: it sets no caution or risky label, and where it is the only record that would, the vendor''s rating is withheld (rating_withheld, reason unconfirmed) rather than reported as stable; a standing narrowing with it also withholds a favourable stability class; and our pages mark the record unconfirmed. Every other outcome leaves the record counting as it did before the check.'
            properties:
              checked:
                type: string
                format: date
                description: The day we ran the check.
              outcome:
                type: string
                enum:
                - vendor_changed
                - ours
                - removal_stated_before
                - no_usable_capture
                - text_day_unknown
                - page_unreadable_today
                description: '''vendor_changed'' — archived copies show the vendor''s page changing. ''ours'' — the archived copy from when our listing text was written already states what the record calls new, so the difference was in our text, not on the vendor''s page. ''removal_stated_before'' — that archived copy already states the removal, so the removal predates our text. ''no_usable_capture'' — no archived copy could settle the record either way. ''text_day_unknown'' — we do not know when our listing text was written, so there was no capture to compare. ''page_unreadable_today'' — we could not read the vendor''s page when we ran the check, so no comparison ran.'
              brackets:
                type: array
                description: 'Where outcome is vendor_changed: each pair of archived copies between which the page changed, the last showing the old terms and the first showing the new. Where there is exactly one, date_meaning is effective_by: the change took effect after last_old and on or before date.'
                items:
                  type: object
                  properties:
                    last_old:
                      type: string
                      format: date
                      description: The day of the last copy showing the old terms.
                    first_new:
                      type:
                      - string
                      - 'null'
                      format: date
                      description: The day of the first copy showing the new terms, or null where only our own read of the page shows them.
                    last_old_capture:
                      type:
                      - string
                      - 'null'
                      format: uri
                      description: That copy's address in the Internet Archive.
                    first_new_capture:
                      type:
                      - string
                      - 'null'
                      format: uri
                      description: That copy's address in the Internet Archive.
                  required:
                  - last_old
                  - first_new
              capture_day:
                type:
                - string
                - 'null'
                format: date
                description: 'Where outcome is ours or removal_stated_before: the day of the archived copy from when our listing text was written.'
              capture:
                type:
                - string
                - 'null'
                format: uri
                description: That copy's address in the Internet Archive.
              stated_then:
                type:
                - string
                - 'null'
                description: 'The line in that copy that settled the check, as the copy prints it: the terms the record called new (ours), or the removal (removal_stated_before).'
              recorded_as:
                type:
                - string
                - 'null'
                enum:
                - free_tier_removed
                - open_source_killed
                - product_deprecated
                - limits_reduced
                - restriction
                - pricing_restructured
                - pricing_model_change
                - limits_increased
                - new_free_tier
                - new_tier
                - startup_program_expanded
                - pricing_postponed
                - rebranded
                - record_corrected
                - null
                description: 'Where outcome is ours: the change type our re-read recorded. The record''s change_type is record_corrected.'
            required:
            - checked
            - outcome
        required:
        - standing
        - date_meaning
        - ends_a_free_tier
      description: 'A change record as /api/changes serves it: every field of DealChange, plus a standing on every record rather than only on the ones we have withdrawn.'
    ChangeResolution:
      type:
      - object
      - 'null'
      description: Present when the change this record describes is no longer in force. state is 'reversed' when the vendor ended it and 'retracted' when the record was our error. date is the day from which it stopped being in force, or the day we established that, whichever we can source. resolved_by names the change record that ended it, when one exists. A record carrying this field never rates the vendor.
      properties:
        state:
          type: string
          enum:
          - reversed
          - retracted
        date:
          type: string
          format: date
        detail:
          type: string
        source_url:
          type: string
          format: uri
        resolved_by:
          type: object
          properties:
            vendor:
              type: string
            date:
              type: string
              format: date
            change_type:
              type: string
      required:
      - state
      - date
x-refined-from:
- agentdeals-dev.json
- agentdeals-dev-openapi.json