Compare Staging vs Production API Schemas
npx typemorph-cli envdiff --a https://staging.api.com/users/1 --b https://prod.api.com/users/1 fetches both endpoints, infers their schemas, and shows field-level breaking changes. No spec files.
The problem
Deploying to production when staging has a different API shape can silently break clients. Manually comparing JSON responses is slow and misses nested changes. OpenAPI diffing tools require you to maintain spec files for both environments.
The solution
typemorph envdiff fetches two live URLs (or reads two local files), infers both schemas, and produces a semantic diff — highlighting removed fields, type changes, and new fields with error/warning/info severity.
Step-by-step
- 1
Run envdiff on two live environments
Pass both endpoint URLs. typemorph fetches them in parallel, infers schemas, and diffs.
Terminal
npx typemorph-cli envdiff \ --a https://staging.api.example.com/users/1 \ --b https://prod.api.example.com/users/1 - 2
Or compare two local response files
Pass file paths instead of URLs to diff saved responses.
Terminal
npx typemorph-cli envdiff \ --a responses/staging-user.json \ --b responses/prod-user.json - 3
Filter to breaking changes only
Use --breaking-only to suppress new-field additions and show only errors.
Terminal
npx typemorph-cli envdiff \ --a https://staging.api.example.com/users/1 \ --b https://prod.api.example.com/users/1 \ --breaking-only - 4
Add to your deployment gate
envdiff exits 1 if breaking changes are found. Chain it before your deploy step.
Terminal
# In your deploy script or CI npx typemorph-cli envdiff \ --a $STAGING_API/users/1 \ --b $PROD_API/users/1 \ --breaking-only \ && echo "Safe to deploy" \ || (echo "Schema mismatch — aborting deploy" && exit 1)
No CLI? Use the web tool
Paste both JSON responses at typemorph.dev/tools/env-diff to see the diff interactively in your browser.
Open TypeMorph WorkbenchFrequently asked
What counts as a breaking change?
Field removed, field type changed to an incompatible type, or required field becoming missing. New fields are flagged as info (not breaking). Enum additions are warnings.
Can I pass auth headers for protected endpoints?
Yes: --header "Authorization: Bearer $TOKEN". The flag can be repeated for multiple headers.
Does it work for deeply nested responses?
Yes. Schema inference is recursive — differences at any nesting level are reported with their full field path.
What if staging and production intentionally have different schemas?
Run with --breaking-only to ignore additions. If you expect certain fields to differ permanently, use separate baselines with the check command instead.