Separate changed data from a changed shape

A project name changing from Atlas to Beacon is usually a data update. A field changing from a Boolean to a string can affect how a client parses a response. A field disappearing may affect code that expects it to exist. These differences deserve different kinds of investigation.

There are also different baselines: a comparison between two published OpenAPI contracts asks whether the declared interface changed; a comparison between two captures asks whether the observed interface changed. Comparing a live response with a published contract is a third task, contract validation.

apispy infers documentation from traffic. A difference between its exports is therefore evidence to investigate, not proof that the server broke its contract. Conversely, unchanged inferred schemas do not rule out changes to ordering, permissions, calculations or other behavior that keeps the same data shape.

Make the two captures comparable

Write a short capture recipe before collecting the baseline. Include the environment, account role, relevant hosts and actions. Keep those conditions as consistent as possible when collecting the second sample.

  1. Open the same list, retrieve a detail record and exercise the same filters and pagination controls.
  2. Include the same kinds of records: for example active and archived projects, empty and populated lists.
  3. Record which success and error outcomes you exercised. A permission error is not a replacement sample for a successful data response.
  4. Use matching domain and tab filters when exporting. Comparing one host with a different host produces misleading additions and removals.
  5. Save the first export separately before collecting or exporting the second. Use clear names such as before.openapi.json and after.openapi.json.

With apispy, continuing an existing session adds observations to the same inferred model. That is useful for expanding coverage, but it can mask removals when the goal is to compare two points in time. Preserve the first export, then collect the second in a separate capture. If you use Reset to begin a fresh capture, it clears the current session; export what you need first.

Compare OpenAPI structure instead of file formatting

For HTTP traffic, inspect method-and-path pairs, parameters, request bodies, response status codes, content types and schema properties. A plain text diff can help with a small document, but reordered keys or changing example values can hide the structural changes you care about.

An OpenAPI-aware tool such as oasdiff can compare saved JSON or YAML specifications. After installing it using its own instructions, run the following command in the directory containing your two files:

Compare two local OpenAPI documents
oasdiff diff before.openapi.json after.openapi.json

See the official command examples. Its breaking command applies compatibility rules to the supplied definitions. With inferred inputs, treat that classification as a review aid because an observed field is not necessarily a server guarantee. This comparison runs in the external tool; it is not a desktop comparison screen in apispy.

GraphQL SDL and AsyncAPI exports need comparison tools appropriate to those formats. Do not pass either document to an OpenAPI comparator. The capture recipe still matters regardless of the export format.

Work through a field removal and a nullable value

These invented project responses illustrate a change worth investigating. They are not results from a production service:

Illustrative responses before and after
Before:
{
  "id": "project_7d8e9f01",
  "name": "Atlas",
  "archived": false
}

After:
{
  "id": "project_7d8e9f01",
  "displayName": "Atlas",
  "archived": null
}

The observations suggest that name disappeared, displayName appeared, and archived can be null. Matching text does not prove a field was renamed. Confirm the intended meaning with another observation or the API owner.

To try the comparison, download the complete illustrative before OpenAPI document and after OpenAPI document. They use api.example.com and are fixtures for local comparison, not an API to call. In the example schemas, the nullable field remains required: being present and accepting null are separate properties.

Check the main sources of false alarms

  • A field is absent only for some records. Compare several equivalent records before calling it a removal. One response may expose an optional case you did not see before.
  • A role or feature flag changed. Account permissions can change visible fields and operations without changing the endpoint for every client.
  • The second capture is shorter. An operation missing from the new export may simply never have been exercised.
  • A response is an error or an empty body. Match status code and content type before comparing schema properties.
  • The observations changed path inference. More examples can reveal that two literal URLs share a parameterized path. Review the raw URLs before interpreting this as an endpoint replacement.
  • The client requested different GraphQL fields. A smaller selection set can look like server schema shrinkage even when the declared type is unchanged.

Use apispy’s Coverage view to identify operations seen once and fields that stayed null. Repeat the uncertain cases rather than treating a sparse sample as a complete baseline.

Decide what the change means for the integration

For each candidate, record the old and new observation, the capture conditions, confidence and the consumer behavior at risk. A client that reads name directly needs a focused check if that field is now absent. A client that already handles null may tolerate a newly observed nullable value.

Request and response changes can affect consumers differently. A newly required request input can invalidate calls that previously omitted it. A response property addition may be harmless to a flexible parser but affect a strict validator. Test the consumer’s actual assumptions rather than relying only on a generic severity label. oasdiff’s compatibility documentation explains its contract-based interpretation.

Also revisit dependent requests. If a producer field supplied the identifier for a later call, the impact can extend beyond the response parser. Save confirmed changes with the reviewed OpenAPI export and keep uncertain differences separate. Repeating a consistent capture recipe makes the next comparison more useful.

Documentation by apispy. Product behavior described here reflects apispy v0.1. Inferred documentation depends on the traffic you observe.