Compare the specification against your version
Save openapi.json with a date, reload it with every train, and compare paths, required fields, and error codes, with the site and your own environment side by side.
3 minute readChangesUpdated: 10/25/2026
On this page
Before you start
- For
- Anyone who operates an integration and wants to check after every train whether it still fits.
- Prerequisite
curl,jq, and Bash (step 5 uses<( … ), which a POSIXshdoes not know). No sign-in is needed, because the specification is public. For the second source, the base address of your environment inSZENERA_API.- Where
- Command line
By the end, you have the specification of the current train, saved with a date, next to that of your environment, and you know whether a path has disappeared, a required field has been added, or a response carries a different status, before your integration notices.
The developer site serves the specification as of the current train at /api/openapi.json. Your environment responds at /v1/openapi.json with what actually runs there. Staging and production can differ, and only the comparison tells you which change you already have in front of you and which one is still coming.
Steps
Load both specifications
-
Save the specification of the site with a date:
curl -sS https://developer.szenera.com/api/openapi.json -o "openapi-$(date +%F).json" -
Place the specification of your environment next to it:
curl -sS "$SZENERA_API/v1/openapi.json" -o openapi-umgebung.json -
Note which version runs there:
curl -sS "$SZENERA_API/health/version"{ "service": "api", "version": "0.4.14", "builtAt": "2026-09-07T10:12:00+02:00", "environment": "production" }
Compare version and paths
-
Compare
info.versionof both files:jq -r '.info.version' openapi-umgebung.json "openapi-$(date +%F).json"Equal numbers do not mean equal content:
info.versionis an operator setting (default1.0.0) and does not move with every train. So always compare the paths as well. -
Compare paths and methods. The command lists every operation as
METHOD /path, anddiffshows what is on only one side:diff <(jq -r '.paths | to_entries[] | .key as $p | .value | keys[] | "\(. | ascii_upcase) \($p)"' openapi-umgebung.json) \ <(jq -r '.paths | to_entries[] | .key as $p | .value | keys[] | "\(. | ascii_upcase) \($p)"' "openapi-$(date +%F).json")
Check required fields, responses, and stability
-
Check the required fields of the schemas you send. The list is in
required:jq -c '.components.schemas.CreateSceneRequest.required' "openapi-$(date +%F).json"["name"] -
Check the responses of the operations you use. The status codes are the keys under
responses, and the error codes for them are in The error format:jq -c '.paths["/v1/scenes/{id}"].patch.responses | keys' "openapi-$(date +%F).json"["200","401","403","404","409","422","429","502"] -
Check
x-stabilityof the operations you use:jq -r '.paths["/v1/scenes/{id}"].patch["x-stability"]' "openapi-$(date +%F).json"The answer is
stableorbeta. The operation in the example isstable.
Check the result
diffin step 5 reports no line with<(only in your environment): no path that you call is removed or moved. Lines with>are new operations and break nothing.- The
requiredlists of the schemas you send contain no field that your requests do not send along. - The status codes under
responsesof your operations are unchanged, and none carriesdeprecated: true. Ifx-stability: betaappears there, the shape can still move, see Stability classes and sunset. - The dated file stays. At the next train, you reload and compare the two dated files with each other.
If something goes wrong
| Symptom | Meaning | Solution |
|---|---|---|
| Your environment still returns the old state after a train | The response of /v1/openapi.json may be cached for five minutes (Cache-Control: public, max-age=300). |
Reload after five minutes. |
info.version is equal, diff still shows differences |
The number in info.version does not follow the train. |
Compare the content, not the number. The running version is named by /health/version. |
| A route is missing in both files but responds | It is classified as internal and therefore not part of the public surface, in neither of the two files. |
Include only public operations in the integration. No promise covers an undocumented route. |
An operation suddenly carries deprecation headers |
It is being sunset. x-sunset in the description and Sunset in the response name the shutdown date. |
Twelve months remain: switch the call to the named successor, see Stability classes and sunset. |
/health/version responds with 429 |
The route is limited to 60 calls per minute and address. | Wait the number of seconds named in Retry-After. |
/health/version reports unknown or a number with -dev |
The environment does not run from a release image. | For the comparison, use the specification, not the version. |