Shared Responses
Shared responses let you define a response once and reuse it across many operations.
This is most useful for repeated error cases such as validation, unauthorized access, or not found responses.
Start inline, extract when repetition appears
For a small API, inline responses are fine. Once the same response shows up across multiple operations, move it into a shared definition.
That keeps your spec shorter and makes client behavior more consistent.
Define shared responses once
import { defineResponse, HttpStatusCode } from "@rexeus/typeweaver-core";
import { z } from "zod";
export const ValidationErrorDefinition = defineResponse({
name: "ValidationError",
statusCode: HttpStatusCode.BAD_REQUEST,
description: "Request validation failed",
body: z.object({
message: z.string(),
}),
});
export const TodoNotFoundErrorDefinition = defineResponse({
name: "TodoNotFoundError",
statusCode: HttpStatusCode.NOT_FOUND,
description: "Todo was not found",
body: z.object({
message: z.string(),
todoId: z.string(),
}),
});
Reuse them in operations
const sharedTodoErrors = [ValidationErrorDefinition, TodoNotFoundErrorDefinition];
const GetTodoDefinition = defineOperation({
operationId: "GetTodo",
summary: "Get todo",
method: HttpMethod.GET,
path: "/todos/:todoId",
request: {
param: z.object({
todoId: z.string(),
}),
},
responses: [GetTodoSuccessDefinition, ...sharedTodoErrors],
});
const UpdateTodoDefinition = defineOperation({
operationId: "UpdateTodo",
summary: "Update todo",
method: HttpMethod.PATCH,
path: "/todos/:todoId",
request: {
param: z.object({
todoId: z.string(),
}),
body: z.object({
title: z.string().min(1).optional(),
}),
},
responses: [UpdateTodoSuccessDefinition, ...sharedTodoErrors],
});
Why this improves the API
Shared responses help because they:
- keep repeated error contracts identical
- reduce copy-paste drift between operations
- make client handling more predictable
They also show up naturally in generated response unions, so clients still work with them through response.type.
Keep response names globally unique
Response names are global across the spec, not local to one operation.
That means names like ValidationError or TodoNotFoundError must be unique everywhere. Choose names that stay clear when reused outside their original file.
When to go further
If you later need to specialize a shared response for a few operations, Typeweaver supports Derived Responses. Most teams should start with plain shared defineResponse(...) definitions first.