Articles
OpenAPI Interview Questions: Schemas, Compatibility, and Generated Clients
Prepare OpenAPI interview questions with schema examples, a tested compatibility matrix, generated-client failure modes, and practical API release checks.
A team adds refunded to an order-status enum. The OpenAPI file validates, the server tests pass, and a newly generated SDK works. An older mobile app then fails to decode the response. Nothing in that sequence is contradictory: the team tested its new contract, not compatibility with the consumer already installed on a customer's phone.
Strong answers to OpenAPI interview questions separate three contracts: the schema accepted by a validator, the HTTP messages exchanged at runtime, and the programming interface exposed by a generated client. A change can preserve one while breaking another. Start with the consumer and the deployment direction before calling a change “additive.”
This article focuses on an order-contract review and the evidence needed to release it safely.
What does an OpenAPI validation pass actually prove?
It establishes the checks performed by that validator against its supported specification version. It does not prove that the running endpoint implements the description, that every generated client behaves alike, or that old consumers accept new output. Name the tool and version before expanding the claim.
The OpenAPI specification describes HTTP interfaces independently of implementation language. The examples here deliberately target OAS 3.1.2 and its JSON Schema foundation. The latest specification was 3.2.1 when checked on September 21, 2026; that does not imply every validator or generator supports it equally.
Distinguish document validation from payload validation. A valid document can describe a required string while the server returns an integer. A payload checker also needs the applicable operation, status, media type and schema. A JSON parser alone checks neither contract.
An interview-ready answer is: “I would validate the description, test representative wire messages, then run the consumer versions we still support. Those are separate gates.” That answer leaves room for behavioral guarantees such as authorization and idempotency, which a structural schema cannot establish by itself.
Are optional and nullable fields the same?
No. Presence and value are separate dimensions. The JSON Schema object reference explains that listing a property under properties does not require its presence. The enclosing object's required array does that. The null reference explains that an explicit null is a value, not an absent key.
Consider this OAS 3.1 schema fragment:
Order:
type: object
required: [id, status]
properties:
id:
type: string
status:
type: string
enum: [pending, paid]
note:
type: [string, "null"]
additionalProperties: false
note may be absent, a string or null. status must be present and one of the two strings. Writing status: null cannot satisfy that enum. Do not copy a 3.0-style nullable assumption into a 3.1 schema without checking the dialect and tooling.
The distinction matters especially for updates. In a hypothetical order-edit endpoint, omission might mean “leave the note unchanged,” while null means “clear the note.” Those meanings are an application decision, not automatically supplied by this schema. State them explicitly and test the two requests separately.
Likewise, making the request body required and making a property required answer different questions. A client can send a body containing {}. The operation-level body requirement alone does not require id or status inside that object.
Review changes in the direction they travel
Assume the existing service accepts requests from old clients and returns responses to them. Ask whether previously accepted requests remain accepted, and whether newly possible responses remain understandable. The following is a worked review, not a universal compatibility policy.
| Proposed change | Old client to new server | New server to old client | Evidence to request |
|---|---|---|---|
| Require a new request field | Old requests may now be rejected | Not the main issue | Replay an old serialized request |
| Accept another request enum value | Existing values can still work | Not automatically a response change | Check server semantics and rollback |
| Return a new response enum value | Requests can remain unchanged | Old decoder or business switch may fail | Decode the new value with the old SDK |
| Add an optional response property | Requests can remain unchanged | Strict unknown-field readers may reject it | Test actual deserializer settings |
| Stop returning a required response field | Requests can remain unchanged | Old code may rely on its presence | Decode and exercise dependent behavior |
| Rename an operation identifier | Wire route can remain identical | Regenerated source interface may change | Compile a representative caller |
This also exposes rollout direction. A new client sending the new request enum to an old server can fail even if old clients remain compatible with the new server. “Backward compatible” is too vague unless you specify which versions communicate.
Treat absence of traffic as different from proof of absence of consumers. An infrequently used integration might not appear in yesterday's logs. Combine telemetry with the supported-client inventory and an explicit deprecation policy before removing behavior.
Run a small old-schema versus new-schema probe
For the order example, create a new schema by adding refunded to the status enum and an optional string receipt property. Keep both schemas closed with additionalProperties: false. A local probe using Python jsonschema 4.26.0 and Draft202012Validator produced these results:
| Order payload variation | Old schema | New schema |
|---|---|---|
id and status: paid; note absent | Pass | Pass |
Same order with note: null | Pass | Pass |
status absent | Fail | Fail |
status: null | Fail | Fail |
status: refunded | Fail | Pass |
status: paid plus receipt: r2 | Fail | Pass |
The core check is deliberately small:
from jsonschema import Draft202012Validator
payload = {"id": "o7", "status": "refunded"}
assert not Draft202012Validator(old_schema).is_valid(payload)
assert Draft202012Validator(new_schema).is_valid(payload)
Here old_schema and new_schema are Python dictionaries containing the two schema definitions. This is a JSON Schema subset test, not validation of the complete OpenAPI document. It also does not execute a generated SDK or a real order service.
The useful conclusion is narrow: two new outputs that satisfy the new schema violate the old closed contract. An old client might ignore unknown properties, but that would be a separate observed client behavior. Do not turn a schema test into an unperformed SDK test.
Why can generated clients break without an HTTP change?
A generator translates descriptions into language-specific types and methods. Changes in naming, generator version, templates or library options can alter that interface even when the method and URL remain stable. Review generated diffs alongside the specification diff.
The OpenAPI Generator usage documentation exposes separate validation and generation commands. The customization documentation documents configuration, naming and template controls. Record those inputs in the build so a regenerated SDK is reproducible rather than dependent on a developer's current defaults.
For a concrete implementation-dependent case, the Java generator options document enumUnknownDefaultCase. It can provide a fallback enum member for unknown values. Its existence is not a guarantee that a previously shipped SDK has that option, or that the application's business logic handles the fallback safely.
Imagine an order screen that treats every non-pending value as paid. A tolerant decoder prevents a parse error but can still display a refunded purchase incorrectly. Compatibility testing must reach the consumer behavior, not stop after object construction.
Separate two experiments: run the unchanged released SDK against new response fixtures, and regenerate an SDK from the new description and compile existing application source against it. The first examines deployed wire compatibility; the second examines an upgrade's source compatibility. Passing only the second hides the installed-client problem from the introduction.
How should you explain oneOf and discriminators?
The JSON Schema combination rules require exactly one matching branch for oneOf, versus at least one for anyOf. Do not describe oneOf as “pick whichever class is convenient.” A payload matching two branches fails that rule.
Suppose an order result is either a receipt or a rejection. Give each branch a required kind with a distinct constant, such as receipt or rejected, and require the branch-specific fields. Test one valid value per branch, an unknown kind, a missing kind and an ambiguous object.
In OAS 3.1.2, a discriminator can guide tooling, but it cannot change the schema's validation outcome. A mapping does not repair branches that overlap. Explain the constraints first, then how the chosen generator represents them. This avoids promising identical union support across languages and libraries.
If the interviewer asks about inheritance, distinguish reuse from substitutability. Combining required properties with allOf means all constraints apply; it is not permission to relax a parent's constraints. A smaller explicit response model can be easier to maintain than a clever hierarchy whose generated classes behave differently across SDKs.
What should the release gate contain?
Build a compact matrix around versions you actually support. For this order change, include the old released client with the new server, the new client with the new server, and the new client with the rollback server. Where the last combination is intentionally unsupported, constrain rollout so it cannot occur silently.
Use fixtures that challenge representation: omitted and null notes, unknown enum values, unknown fields, error bodies, and the chosen numeric and date encodings. For query parameters, compare the serialized URL as well as the in-memory argument. A list encoded with commas is not interchangeable with repeated keys unless the endpoint contract permits both.
Make release failures actionable. A document-validation error belongs to the description author; an old-client decoding failure needs a compatibility decision; a source compilation error needs an SDK migration or naming repair. Labeling all three “OpenAPI failed” sends the investigation to the wrong layer.
For the refunded-status change, a defensible plan is to ship and verify tolerant handling first, measure adoption where possible, then enable the new response value under a controlled rollout. If some supported consumers cannot change, preserve their contract or introduce an explicitly negotiated version. Do not simply suppress validation until the release turns green.
Practise defending the compatibility claim
Explain the old message, the changed rule and the consumer behavior you would observe.
| Practice question | OpenAPI-focused follow-up |
|---|---|
| Validate JSON against a protobuf-like schema | Separate missing values, nulls and type mismatches. |
| Reason About Nested JSON Schema Validation | Prove that union branches match as intended. |
| Implement CRUD API and tests | Compare the written contract with actual responses. |
| Debug and Harden a Ticketing Backend API | Preserve consumer behavior while repairing validation. |
| Implement paginated API ingestion | Test a client across response and pagination changes. |
Return to the backend engineer guide to connect contract decisions with storage and deployment design. Your strongest closing sentence is specific: “This change is compatible with these consumer versions, in this direction, and these tests are the evidence.”