> [Agent navigation index](/llms.txt)

# OpenAPI Contract Generation

Brix generates Zod schemas and typed API contracts from Swagger/OpenAPI 2.0 and OpenAPI 3.0/3.1 definitions. Generated contracts are universal: they can be consumed from a Brix application, a Node service, a worker, a library, or an external browser client with the standard Fetch API.

## Generate one specification

```sh
brix openapi generate ./openapi/catalog.yaml --out src/generated/catalog-api --name catalog

```

The input can be a local file or an HTTP(S) URL. External references are resolved and bundled. The example assumes the application owns `openapi/catalog.yaml`.

The output directory is completely generated. Every successful run replaces all of its contents, including unexpected files. Never store handwritten code or unrelated tool output there. Brix rejects paths outside the project and symbolic-link traversal.

## Configure multiple definitions

Create `brix.openapi.ts` at the owning project root:

```ts
import { defineBrixOpenApiConfig } from "brix/config";

export default defineBrixOpenApiConfig({
  name: "commerce",
  out: "src/generated/commerce-api",
  definitions: {
    catalog: "openapi/catalog.yaml",
    accounts: "openapi/accounts.json",
  },
  strict: true,
});

```

```sh
brix openapi generate
brix openapi generate --config config/apis.ts

```

Definition paths and `out` are relative to the selected project root, not the config directory. Within a workspace, use `brix openapi#storefront generate` for the owning member.

## Import the public generated root

The configured name determines the aggregate export. A single specification named `catalog` exposes `catalogContracts`; multiple definitions named `commerce` expose `commerceContracts` with definition namespaces.

```ts
import { catalogContracts, type CatalogUser } from "./generated/catalog-api/index.ts";

```

The exact members depend on the specification. For example, a `products` tag with a `getProduct` operation and a `User` schema produces access through:

```ts
catalogContracts.products.getProduct;
catalogContracts.schemas.catalogUserSchema;

```

Contracts are grouped by their first tag by default. `--group-by none` uses a nested `contracts` group instead. Multi-definition output adds definition prefixes and collision-safe namespaces. Repeated adjacent prefixes are collapsed rather than producing names such as `CommerceCatalogCatalog`.

Import only the generated top-level `index.ts`. Internal module paths are implementation details and can change as the specification evolves.

## Consume a generated contract

Generated modules import `brix/contracts` and `brix/zod`. They do not require Hono, a server setup file, route discovery, or a running Brix application.

For the illustrative `getProduct` operation above, whose path declares `productId`:

```ts
import { createApiClient } from "brix/contracts";
import { catalogContracts } from "./generated/catalog-api/index.ts";

const client = createApiClient({ baseUrl: "https://catalog.example.com/api/v1" });
const result = await client.execute(catalogContracts.products.getProduct, {
  params: { productId: "sku-123" },
});

if (result.isOk()) console.log(result.value);
else console.error(result.error.kind);

```

Set `baseUrl` explicitly and include any path prefix from the selected OpenAPI server URL. Configure credentials and required header/cookie values at the request/client boundary; the generator does not implement authentication for you. See [API clients](/docs/api-routes) and [caching](/docs/caching).

## Review and enforce drift

```sh
brix openapi generate --dry-run
brix openapi generate --check
brix check

```

Generation is deterministic. The `.brix-openapi.json` manifest records generated output so `--check` detects changes and unexpected files without writing. Use it in CI with the same input and options as local generation. Review specification and generated-code changes together.

## Serialization boundaries

Brix fails operations it cannot represent faithfully instead of silently altering their HTTP behavior:

- Request bodies must have one `application/json` representation.
- GET bodies, unsupported methods, unsupported success bodies, and complex or reserved query serialization are rejected.
- Colliding tag namespaces fail generation.
- Numeric and boolean query inputs are decoded from their URL representation before validation.
- OpenAPI `2XX`, bodyless, and `default` success responses remain represented in the runtime response union.

Authentication requirements, header/cookie parameters, path-parameter schemas, error-response schemas, and optional bodies produce warnings where the current runtime does not own the complete semantics. `--strict` turns every warning into a failure. Investigate each warning; do not simply remove strict mode to accept an incorrect client.

Keep handwritten endpoint adapters outside the generated directory when an API needs behavior that cannot be represented by the contract runtime. The generated schemas describe the supported wire boundary, not arbitrary application validation or server implementations.
