OpenAPI describes the refusal too

OpenAPI describes HTTP paths, operations, request bodies, and responses. An agent can read our generated /openapi.json before choosing an HTTP call.

apps/site/src/app.ts builds the /api projection. It passes the API to HttpApiBuilder.layer, with openapiPath: "/openapi.json".

Effect’s OpenApi.fromApi derives the document from that HttpApi.

The document must describe rejected request input

Commit 8766790 adds HttpApiError.BadRequestNoContent to every endpoint built by toHttpApi. Request decoding already returns an empty 400. The document needs to say so.

The rejected request input produces an empty response body rather than application/problem+json. The route test sends an invalid payload and checks:

The document has a BadRequest response description with no content field. A reader uses that distinction to decide whether to parse the error body.

A declared failure defaults to 422 unless its schema names another HTTP status. A plain union keeps each member’s status, including on default POST routes. Projects created from the template with annotated union members now receive those statuses instead of 422.

A refinement adds a check that limits accepted values. Checked or refined unions retain their whole-union status.

A declared domain failure differs from a request decode failure. See schema-driven development17 for that boundary. See generating surfaces23 for the document’s source.

See how we do it with Effect9 for the whole path.

Sources

  1. OpenAPI 3.1.0 specification. Primary source. OpenAPI 3.1.0 specification Accessed 2026-10-02.
  2. apps/site/src/app.ts. GitHub. apps/site/src/app.ts Accessed 2026-10-02.
  3. packages/capability/src/to-http-api.ts. GitHub. packages/capability/src/to-http-api.ts Accessed 2026-10-02.
  4. Document empty HTTP decode failures. GitHub. Document empty HTTP decode failures Accessed 2026-10-02.
  5. packages/capability/test/to-http-api-routes.test.ts. GitHub. packages/capability/test/to-http-api-routes.test.ts Accessed 2026-10-02.
  6. Effect 4 OpenApi.fromApi. GitHub. Effect 4 OpenApi.fromApi Accessed 2026-10-02.

Last changed 2026-10-10 in 978dccc. Source on GitHub. Change log.

Linked from

  1. add-a-capability. Learn how one contract and its handler become a command, HTTP route, MCP tool, browser RPC, and sandbox call.

    HTTP adds POST /doThing and updates OpenAPI.¶

  2. Agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.

    OpenAPI describes the refusal too — The generated HTTP contract declares inputs, outputs, and the bodyless 400 returned when decoding fails.

  3. An agent applied through Markdown and HTTP. One observed application used the Markdown page and llms.txt, then one POST; confirmation followed 88 seconds later.

    Other calls may need OpenAPI or MCP.¶

  4. Build and run rat-stack (README.md). What is in the repo, how the example works, and how to run it.
  5. Capabilities. Named application actions exposed through generated interfaces share one definition and one server-side implementation.

    JSON Schema, OpenAPI, and the code-mode declarations are derived from them, never written by hand.¶

  6. Change log. What changed in the files served here, newest first.

    OpenAPI describes the refusal too — edited: docs: point live docs, skills and Brain pages at apps/site

  7. Effect keeps the surfaces on one contract. Schema owns values, projections build interfaces, and Layers supply implementations.

    OpenAPI describes the refusal too: derive the HTTP document and declare the bodyless decode failure.¶

  8. Full agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
  9. keep-or-cut. Learn which pieces depend on each other, then keep only the ones your project needs.

    the OpenAPI case from apps/cli/test/cli.e2e.test.ts¶

  10. One schema, three surfaces. A capability contract feeds CLI, HTTP, and MCP; OpenAPI is generated output, not their input.

    my approach wrt to the agentic backend is to cover cli/api/mcp with a single openapi schema that is used to generate all three¶

  11. Rat Stack lore | rat-stack. Short, source-grounded notes on the ideas and decisions behind rat-stack.

    OpenAPI describes the refusal too — The generated HTTP contract declares inputs, outputs, and the bodyless 400 returned when decoding fails.

  12. rat-stack. An Effect stack so pure (aspirational) Kit Langton will blush.
  13. Schema projections: 2026-09-18 history. Historical Effect rc.115 proposal and implementation receipts from 2026-09-18; use the one-capability-every-surface lore page for the current pattern.
  14. Schemas define the boundary. Define accepted data with Schema, decode unknown input before dispatch, and encode results through the declared contract.

    See also: one schema, three surfaces, OpenAPI refusals, services, and testing.¶

  15. Source change history (log.md). The generated change log as Markdown.

    OpenAPI describes the refusal too — edited: docs: point live docs, skills and Brain pages at apps/site