← All decisions

5. OpenAPI 3.1.0 with Schemathesis 3.1 support enabled

Date: 2026-07-16

Status

Accepted

Context

The contract is written in OpenAPI 3.1.0, the current version, which aligns the JSON Schema dialect with standard JSON Schema and lets us express nullable fields as type: [string, "null"] instead of the 3.0 nullable: true wart.

Schemathesis 3.39.5, our contract-test fuzzer, treats 3.1 as experimental and refuses to load such a spec unless the support is explicitly enabled.

Decision

Keep the contract at 3.1.0 and enable Schemathesis's 3.1 support with schemathesis.experimental.OPEN_API_3_1.enable() in the test harness. We do not downgrade the contract to 3.0.3 to placate one tool.

We also document a shared 400 Bad Request response on every operation. Fuzzing proved the HTTP layer legitimately returns 400 for malformed requests (a corrupt pagination cursor at the application level, or control characters in a header that the server rejects before the application runs). The contract now tells the truth about this, including that protocol-level rejections may carry a plain-text body rather than the JSON envelope.

Consequences

  • The contract uses modern, correct syntax.
  • The test harness carries one line of setup and a comment pointing here.
  • A future Schemathesis that supports 3.1 by default makes that line redundant; it is harmless until then.
  • Documenting the 400 forced us to fix a real bug: a malformed cursor used to reach Postgres and return 500. It now returns 400 before touching the database. The fuzzer earned its keep on day one.