APIs change. Providers rename fields, add required parameters, and retire endpoints, and most don’t tell you which of your calls are affected. apiweld check compares the provider’s current spec with the version in your lockfile and reports only changes to the endpoints you use.
Run it whenever you like: by hand, in a pre-commit hook, on a schedule in your CI, or from your agent with check_drift. Apiweld doesn’t run anything on a server, so you decide when checks happen.
npx apiweld checkWhat gets reported
Only changes that affect your selected endpoints. If Stripe adds a field to an endpoint you don’t call, check stays quiet. If Stripe changes a schema that one of your endpoints uses, that change is reported against every selected endpoint that uses the schema.
Each change gets one of three labels:
| Label | What it means | Examples | What Apiweld does |
|---|---|---|---|
| Breaking | Code that works today will fail. | An endpoint was removed. A request field became required. A response field was removed or changed type. An allowed request value was removed. | Writes a heal plan. Never regenerates on its own. |
| Risky | Might break you, depending on how you use it. | A new value appeared in a response enum. A field became nullable. The auth scheme changed. The endpoint was deprecated. | Regenerates in a separate worktree, type-checks your project, and reports the result. |
| Safe | Nothing you use can break. | A new optional field or parameter. A description changed. | Regenerates automatically if the API’s policy.autoRegenerate is "safe". |
The labels come from oasdiff, which has a rule for each kind of change. Its ERR level becomes breaking, WARN becomes risky, and INFO becomes safe.
If a provider’s conventions make one rule fire on changes that don’t matter to you, re-label that rule for that API with levelOverrides. The override lives in your config and applies to that API only.
How a check runs
Fetch only if something changed
Apiweld requests the spec with the ETag from the last fetch. If the provider says nothing changed, or the new spec is byte-for-byte the same, the check ends here.
Normalize and slice
The new spec is normalized (references resolved, keys sorted, Swagger 2.0 upgraded to OpenAPI 3) and cut down to your endpoints and the schemas they use. That’s the slice. If one of your endpoints no longer exists, that’s recorded as a breaking change.
Skip changes you don't use
If the spec changed but your slice didn’t, the change was somewhere you don’t use. The lock is updated and nothing is reported.
Compare and label
oasdiff compares the old and new specs. Apiweld keeps only the findings for your endpoints and labels each one.
Report
Results print as a table, or as JSON with --json. A Markdown report is also written to .apiweld/reports/.
Use it as a CI gate
check exits with a non-zero code when it finds a breaking change. To also fail on risky changes, use --fail-on risky.
npx apiweld check --fail-on riskyTo have CI open a pull request with the fix, see Heal in CI.
Apply safe updates
apiweld update runs a check and then applies what your policy allows. Safe changes regenerate in place when policy.autoRegenerate is "safe". Risky changes are reported with their type-check results. Breaking changes stop at the heal plan.
Runtime drift
Specs aren’t always accurate. Sometimes the live API returns something the spec doesn’t describe. With validators: "zod", the generated client includes a reportingFetch that checks each response against the spec’s schema without blocking anything:
import { client } from "./apis/stripe/client.gen";
import { reportingFetch } from "./apis/stripe";
client.setConfig({ fetch: reportingFetch });When a response doesn’t match, one line is appended to .apiweld/drift.log.jsonl with the endpoint, the JSON path, the expected type, the received type, and a timestamp. Response values are never logged. The next apiweld check includes these entries in its report, next to the spec changes.
