hassan-jahan/api-delta-manifest

A machine-readable feed of API changes, built for both AI agents and humans so they can act on them easily

3

stars

4

commits

Sep 1, 2026

updated

ai-agent
ai-agents
api
api-integration
migration
openapi
vibe-coding

README

validate spec version

API Delta Manifest (ADM)

API Delta Manifest

A machine-readable feed of API changes, built for both AI agents and humans so they can act on them easily

The problem

Every backend team eventually depends on APIs it doesn't control. When a provider changes something, that information usually arrives as a paragraph in a changelog, a blog post, or an email that gets filtered into a folder no one opens. Nothing in that format tells a computer which endpoint changed, how severe the change is, or what code needs to move. So teams find out at runtime, when a request starts failing in production.

Meanwhile, coding agents (Claude Code, Devin, Cursor, GitHub Copilot workspace agents, and similar tools) are now routinely trusted to read a codebase and open a pull request. That capability is underused here, because there's nothing structured for an agent to read on the provider side. Changelog text is written for humans skimming a page, not for a script deciding whether to touch payment-service/src/charges.ts.

API Delta Manifest (ADM) closes that gap. It defines a small, strict JSON format that API providers publish alongside their existing changelog, describing every change in a shape that a script — or an agent — can parse, filter, and act on without guessing.

This repository defines v1 of the ADM spec, scoped intentionally to one piece: the manifest file itself. Codemod delivery, webhooks, and consumer-side tooling are natural next steps but are out of scope for v1 so the core format can stabilize first.

Design goals

  • Deterministic, not descriptive. A field like severity must be one of a fixed set of values. No agent should have to infer meaning from freeform prose to decide whether a change is safe to ignore.
  • Diffable. Each entry is addressable by a stable id, so consumers can track "which changes have I already applied" the same way they track applied database migrations.
  • Additive to what providers already do. ADM does not replace a human-facing changelog page. It sits next to it as a structured export of the same information.
  • Small enough to hand-write, strict enough to validate. A JSON Schema ships with this spec so a manifest can be checked in CI before publishing.

Where it lives

Providers publish the manifest at a fixed, discoverable path:

https://api.example.com/.well-known/api-delta-manifest.json

This follows the existing .well-known convention (the same one used by security.txt and OAuth discovery documents), so consumers and agents don't need provider-specific configuration to find it — they can always check the same relative path.

Manifest structure

{
  "adm_version": "1.0",
  "provider": "acme-payments",
  "generated_at": "2026-09-01T12:00:00Z",
  "latest_snapshot": "2026-08-28",
  "entries": [
    {
      "id": "acme-2026-08-28-001",
      "released_at": "2026-08-28",
      "severity": "breaking",
      "kind": "field_rename",
      "title": "charges.source renamed to charges.payment_method",
      "description": "The `source` field on the Charge object is renamed to `payment_method`. The old field remains readable but not writable until the sunset date.",
      "surface": {
        "endpoints": ["POST /v1/charges", "GET /v1/charges/{id}"],
        "fields": ["charges.source"],
        "sdk_packages": [
          { "ecosystem": "npm", "name": "@acme/payments-node", "min_safe_version": "6.2.0" },
          { "ecosystem": "composer", "name": "acme/payments-php", "min_safe_version": "4.0.0" }
        ]
      },
      "action": {
        "required": true,
        "auto_fixable": true,
        "guidance": "Replace reads and writes of `source` with `payment_method`. No value transformation needed.",
        "codemod_url": "https://cdn.acme.com/adm/codemods/acme-2026-08-28-001.js",
        "docs_url": "https://docs.acme.com/changes/acme-2026-08-28-001"
      },
      "sunset_at": "2027-02-28",
      "supersedes": null
    }
  ]
}

Top-level fields

FieldTypeRequiredNotes
adm_versionstringyesSpec version this document conforms to, e.g. "1.0".
providerstringyesShort, stable, lowercase-hyphenated identifier for the API. Should not change once published.
generated_atstring (ISO 8601)yesTimestamp the file was generated. Consumers can use this to detect staleness.
latest_snapshotstring (ISO 8601 date)yesThe date-based version identifier of the newest API revision described here.
entriesarray of Entry objectsyesOne object per change. Newest first. Never delete or mutate a past entry; append instead.

Entry fields

FieldTypeRequiredNotes
idstringyesGlobally unique, stable, never reused. Recommended pattern: {provider}-{date}-{sequence}.
released_atstring (ISO 8601 date)yesWhen the change went live.
severityenumyesOne of: breaking, deprecation, additive, patch. See table below.
kindenumyesOne of: field_rename, field_removal, field_addition, endpoint_removal, endpoint_addition, behavior_change, auth_change, rate_limit_change, other.
titlestringyesOne line, plain text, no markdown. Should be understandable without reading description.
descriptionstringyesPlain-language explanation. Markdown allowed. This is the only field meant primarily for a human reader; agents should rely on the structured fields, not parse this one.
surfaceobjectyesSee below. Describes exactly what changed.
actionobjectyesSee below. Describes what a consumer (or their agent) should do about it.
sunset_atstring (ISO 8601 date) or nullnoDate after which the old behavior stops working. Omit or null if there is no deadline (e.g. purely additive changes).
supersedesstring or nullnoThe id of an earlier entry this one revises or corrects, if any.

surface object

FieldTypeRequiredNotes
endpointsarray of stringsnoEach formatted as "{METHOD} {path}", e.g. "POST /v1/charges". Use the path template with parameter placeholders (e.g. {id}), not a resolved URL. Supports ANY in place of a method — see below.
fieldsarray of stringsnoDot-notated, e.g. "charges.source".
sdk_packagesarray of objectsnoEach has ecosystem (npm, composer, pip, gem, go, etc.), name, and min_safe_version — the first package version where this change is already reflected.

At least one of endpoints, fields, or sdk_packages must be present — an entry with an empty surface gives a consumer nothing to match against and should not validate.

Method and path matching

endpoints entries are "{METHOD} {path}" strings:

  • Path templates use parameterized placeholders like {id} or {customer_id} for variable segments (e.g. "GET /v1/customers/{id}/invoices" or "POST /v1/charges"). Wildcards (like *) are not used in paths — route paths should be explicitly defined with parameter placeholders to ensure precise and deterministic matching.
  • ANY as the method matches every HTTP method on that path. Use this when a change affects a route regardless of verb — for example, an auth change that applies to GET, POST, and DELETE on the same resource alike:
    "ANY /v1/charges/{id}"
    

If a change affects multiple endpoints across an API, list each specific endpoint template instead of using broad patterns. Consumers and AI agents rely on explicit route definitions in surface to target code patches accurately without having to guess.

action object

FieldTypeRequiredNotes
requiredbooleanyesWhether a consumer must change anything to remain compatible. false for purely additive changes.
auto_fixablebooleanyesWhether a mechanical code transform can resolve this without human judgment.
guidancestringyesPlain-language instruction for what to change. Written so an agent can act on it even without codemod_url.
codemod_urlstring (URL) or nullnoLink to a runnable transform (e.g. a jscodeshift script, a Rector rule, an ast-grep pattern). Present only when auto_fixable is true.
docs_urlstring (URL) or nullnoLink to full human-readable documentation of the change.

severity values

ValueMeaning
breakingExisting integrations will fail or misbehave unless updated.
deprecationCurrent behavior still works but is scheduled for removal by sunset_at.
additiveNew capability. Nothing existing is affected.
patchBug fix or clarification with no expected impact on correctly-written integrations.

Example

examples/acme-payments.api-delta-manifest.json is a complete, valid manifest for a fictional payments API. It deliberately covers all four severities and shows the ANY method and parameterized path templates in use (acme-2026-08-10-004 and acme-2026-08-28-001), so it can double as a reference when writing or generating a manifest of your own.

Validation

A JSON Schema is provided in this repo. Providers should validate every manifest against it before publishing, ideally as a CI step that fails the build on an invalid document.

Validating locally

npm install
npm run validate

This runs ajv-cli against every file in examples/ using schema/adm-v1.schema.json. Point it at your own manifest with:

npx ajv validate -s schema/adm-v1.schema.json -d path/to/your-manifest.json --strict=true

Guidance for AI agents generating or consuming a manifest

If you are an agent tasked with producing an ADM file on behalf of an API provider:

  1. One entry per discrete change. Do not bundle multiple unrelated field changes into a single entry — a consumer filtering by surface.fields needs each change isolated.
  2. Never omit severity or kind, and never invent values outside the enums above. If a change doesn't cleanly fit an existing kind, use "other" and explain fully in description — do not create a new enum value.
  3. id must be stable and unique before you finalize the entry. Once a manifest is published, treat every existing id as immutable. Re-publishing must append new entries, never rewrite old ones.
  4. Only set action.auto_fixable: true if action.codemod_url actually resolves to a working transform. If no transform exists yet, set it to false and rely on action.guidance alone.
  5. Write action.guidance as an instruction, not a description. Prefer "Replace X with Y" over "The X field was renamed to Y" — the former is directly actionable, the latter requires re-interpretation.
  6. If you are consuming a manifest to patch a codebase, filter entries by severity and surface before reading description, cross-reference surface.sdk_packages[].min_safe_version against the consumer's installed version to skip changes already absorbed by a dependency bump, and only fall back to interpreting description in free text when action.codemod_url is absent and action.guidance is insufficient to write a mechanical patch.
  7. Prefer specific HTTP methods over ANY unless the change truly is method-agnostic. Listing specific methods and route templates gives downstream consumers precision they rely on to avoid unnecessary inspection.

Roadmap

This version defines only the manifest format and its hosting location. Deliberately excluded for now, to keep the core spec stable and reviewable:

  • A push/webhook delivery mechanism for new entries
  • A required format for codemod_url payloads (jscodeshift vs. Rector vs. ast-grep are all currently allowed; a follow-up spec may standardize this)
  • A consumer-side lockfile format for tracking which entries have already been applied

Proposals for any of the above are welcome as issues in this repo.

Contributing

This is a draft specification. See CONTRIBUTING.md for how to propose a change. In short: open an issue describing the problem before proposing a fix, and back up any change to schema/adm-v1.schema.json with a concrete example under examples/ that demonstrates it. Backwards-incompatible changes to the spec itself bump adm_version, following the same discipline the spec asks of API providers — see CHANGELOG.md for how that's tracked here.

License

MIT License.

Contributors

hassan-jahan

4 commits

hassan-jahan/api-delta-manifest

A machine-readable feed of API changes, built for both AI agents and humans so they can act on them easily

3

stars

4

commits

Sep 1, 2026

updated

ai-agent
ai-agents
api
api-integration
migration
openapi
vibe-coding

README

validate spec version

API Delta Manifest (ADM)

API Delta Manifest

A machine-readable feed of API changes, built for both AI agents and humans so they can act on them easily

The problem

Every backend team eventually depends on APIs it doesn't control. When a provider changes something, that information usually arrives as a paragraph in a changelog, a blog post, or an email that gets filtered into a folder no one opens. Nothing in that format tells a computer which endpoint changed, how severe the change is, or what code needs to move. So teams find out at runtime, when a request starts failing in production.

Meanwhile, coding agents (Claude Code, Devin, Cursor, GitHub Copilot workspace agents, and similar tools) are now routinely trusted to read a codebase and open a pull request. That capability is underused here, because there's nothing structured for an agent to read on the provider side. Changelog text is written for humans skimming a page, not for a script deciding whether to touch payment-service/src/charges.ts.

API Delta Manifest (ADM) closes that gap. It defines a small, strict JSON format that API providers publish alongside their existing changelog, describing every change in a shape that a script — or an agent — can parse, filter, and act on without guessing.

This repository defines v1 of the ADM spec, scoped intentionally to one piece: the manifest file itself. Codemod delivery, webhooks, and consumer-side tooling are natural next steps but are out of scope for v1 so the core format can stabilize first.

Design goals

  • Deterministic, not descriptive. A field like severity must be one of a fixed set of values. No agent should have to infer meaning from freeform prose to decide whether a change is safe to ignore.
  • Diffable. Each entry is addressable by a stable id, so consumers can track "which changes have I already applied" the same way they track applied database migrations.
  • Additive to what providers already do. ADM does not replace a human-facing changelog page. It sits next to it as a structured export of the same information.
  • Small enough to hand-write, strict enough to validate. A JSON Schema ships with this spec so a manifest can be checked in CI before publishing.

Where it lives

Providers publish the manifest at a fixed, discoverable path:

https://api.example.com/.well-known/api-delta-manifest.json

This follows the existing .well-known convention (the same one used by security.txt and OAuth discovery documents), so consumers and agents don't need provider-specific configuration to find it — they can always check the same relative path.

Manifest structure

{
  "adm_version": "1.0",
  "provider": "acme-payments",
  "generated_at": "2026-09-01T12:00:00Z",
  "latest_snapshot": "2026-08-28",
  "entries": [
    {
      "id": "acme-2026-08-28-001",
      "released_at": "2026-08-28",
      "severity": "breaking",
      "kind": "field_rename",
      "title": "charges.source renamed to charges.payment_method",
      "description": "The `source` field on the Charge object is renamed to `payment_method`. The old field remains readable but not writable until the sunset date.",
      "surface": {
        "endpoints": ["POST /v1/charges", "GET /v1/charges/{id}"],
        "fields": ["charges.source"],
        "sdk_packages": [
          { "ecosystem": "npm", "name": "@acme/payments-node", "min_safe_version": "6.2.0" },
          { "ecosystem": "composer", "name": "acme/payments-php", "min_safe_version": "4.0.0" }
        ]
      },
      "action": {
        "required": true,
        "auto_fixable": true,
        "guidance": "Replace reads and writes of `source` with `payment_method`. No value transformation needed.",
        "codemod_url": "https://cdn.acme.com/adm/codemods/acme-2026-08-28-001.js",
        "docs_url": "https://docs.acme.com/changes/acme-2026-08-28-001"
      },
      "sunset_at": "2027-02-28",
      "supersedes": null
    }
  ]
}

Top-level fields

FieldTypeRequiredNotes
adm_versionstringyesSpec version this document conforms to, e.g. "1.0".
providerstringyesShort, stable, lowercase-hyphenated identifier for the API. Should not change once published.
generated_atstring (ISO 8601)yesTimestamp the file was generated. Consumers can use this to detect staleness.
latest_snapshotstring (ISO 8601 date)yesThe date-based version identifier of the newest API revision described here.
entriesarray of Entry objectsyesOne object per change. Newest first. Never delete or mutate a past entry; append instead.

Entry fields

FieldTypeRequiredNotes
idstringyesGlobally unique, stable, never reused. Recommended pattern: {provider}-{date}-{sequence}.
released_atstring (ISO 8601 date)yesWhen the change went live.
severityenumyesOne of: breaking, deprecation, additive, patch. See table below.
kindenumyesOne of: field_rename, field_removal, field_addition, endpoint_removal, endpoint_addition, behavior_change, auth_change, rate_limit_change, other.
titlestringyesOne line, plain text, no markdown. Should be understandable without reading description.
descriptionstringyesPlain-language explanation. Markdown allowed. This is the only field meant primarily for a human reader; agents should rely on the structured fields, not parse this one.
surfaceobjectyesSee below. Describes exactly what changed.
actionobjectyesSee below. Describes what a consumer (or their agent) should do about it.
sunset_atstring (ISO 8601 date) or nullnoDate after which the old behavior stops working. Omit or null if there is no deadline (e.g. purely additive changes).
supersedesstring or nullnoThe id of an earlier entry this one revises or corrects, if any.

surface object

FieldTypeRequiredNotes
endpointsarray of stringsnoEach formatted as "{METHOD} {path}", e.g. "POST /v1/charges". Use the path template with parameter placeholders (e.g. {id}), not a resolved URL. Supports ANY in place of a method — see below.
fieldsarray of stringsnoDot-notated, e.g. "charges.source".
sdk_packagesarray of objectsnoEach has ecosystem (npm, composer, pip, gem, go, etc.), name, and min_safe_version — the first package version where this change is already reflected.

At least one of endpoints, fields, or sdk_packages must be present — an entry with an empty surface gives a consumer nothing to match against and should not validate.

Method and path matching

endpoints entries are "{METHOD} {path}" strings:

  • Path templates use parameterized placeholders like {id} or {customer_id} for variable segments (e.g. "GET /v1/customers/{id}/invoices" or "POST /v1/charges"). Wildcards (like *) are not used in paths — route paths should be explicitly defined with parameter placeholders to ensure precise and deterministic matching.
  • ANY as the method matches every HTTP method on that path. Use this when a change affects a route regardless of verb — for example, an auth change that applies to GET, POST, and DELETE on the same resource alike:
    "ANY /v1/charges/{id}"
    

If a change affects multiple endpoints across an API, list each specific endpoint template instead of using broad patterns. Consumers and AI agents rely on explicit route definitions in surface to target code patches accurately without having to guess.

action object

FieldTypeRequiredNotes
requiredbooleanyesWhether a consumer must change anything to remain compatible. false for purely additive changes.
auto_fixablebooleanyesWhether a mechanical code transform can resolve this without human judgment.
guidancestringyesPlain-language instruction for what to change. Written so an agent can act on it even without codemod_url.
codemod_urlstring (URL) or nullnoLink to a runnable transform (e.g. a jscodeshift script, a Rector rule, an ast-grep pattern). Present only when auto_fixable is true.
docs_urlstring (URL) or nullnoLink to full human-readable documentation of the change.

severity values

ValueMeaning
breakingExisting integrations will fail or misbehave unless updated.
deprecationCurrent behavior still works but is scheduled for removal by sunset_at.
additiveNew capability. Nothing existing is affected.
patchBug fix or clarification with no expected impact on correctly-written integrations.

Example

examples/acme-payments.api-delta-manifest.json is a complete, valid manifest for a fictional payments API. It deliberately covers all four severities and shows the ANY method and parameterized path templates in use (acme-2026-08-10-004 and acme-2026-08-28-001), so it can double as a reference when writing or generating a manifest of your own.

Validation

A JSON Schema is provided in this repo. Providers should validate every manifest against it before publishing, ideally as a CI step that fails the build on an invalid document.

Validating locally

npm install
npm run validate

This runs ajv-cli against every file in examples/ using schema/adm-v1.schema.json. Point it at your own manifest with:

npx ajv validate -s schema/adm-v1.schema.json -d path/to/your-manifest.json --strict=true

Guidance for AI agents generating or consuming a manifest

If you are an agent tasked with producing an ADM file on behalf of an API provider:

  1. One entry per discrete change. Do not bundle multiple unrelated field changes into a single entry — a consumer filtering by surface.fields needs each change isolated.
  2. Never omit severity or kind, and never invent values outside the enums above. If a change doesn't cleanly fit an existing kind, use "other" and explain fully in description — do not create a new enum value.
  3. id must be stable and unique before you finalize the entry. Once a manifest is published, treat every existing id as immutable. Re-publishing must append new entries, never rewrite old ones.
  4. Only set action.auto_fixable: true if action.codemod_url actually resolves to a working transform. If no transform exists yet, set it to false and rely on action.guidance alone.
  5. Write action.guidance as an instruction, not a description. Prefer "Replace X with Y" over "The X field was renamed to Y" — the former is directly actionable, the latter requires re-interpretation.
  6. If you are consuming a manifest to patch a codebase, filter entries by severity and surface before reading description, cross-reference surface.sdk_packages[].min_safe_version against the consumer's installed version to skip changes already absorbed by a dependency bump, and only fall back to interpreting description in free text when action.codemod_url is absent and action.guidance is insufficient to write a mechanical patch.
  7. Prefer specific HTTP methods over ANY unless the change truly is method-agnostic. Listing specific methods and route templates gives downstream consumers precision they rely on to avoid unnecessary inspection.

Roadmap

This version defines only the manifest format and its hosting location. Deliberately excluded for now, to keep the core spec stable and reviewable:

  • A push/webhook delivery mechanism for new entries
  • A required format for codemod_url payloads (jscodeshift vs. Rector vs. ast-grep are all currently allowed; a follow-up spec may standardize this)
  • A consumer-side lockfile format for tracking which entries have already been applied

Proposals for any of the above are welcome as issues in this repo.

Contributing

This is a draft specification. See CONTRIBUTING.md for how to propose a change. In short: open an issue describing the problem before proposing a fix, and back up any change to schema/adm-v1.schema.json with a concrete example under examples/ that demonstrates it. Backwards-incompatible changes to the spec itself bump adm_version, following the same discipline the spec asks of API providers — see CHANGELOG.md for how that's tracked here.

License

MIT License.

Contributors

hassan-jahan

4 commits