Skip to main content

Validation

api-def can validate query, body, response, and state values at runtime while keeping the corresponding TypeScript types.

Zod schemas

Install Zod and pass schemas through the { schema } option:

npm install zod
import { Api } from "api-def";
import { z } from "zod";

const API = new Api({
name: "My Backend",
baseUrl: "https://api.example.com",
});

const fetchUser = API
.endpoint()
.queryOf({
schema: z.object({
includeProfile: z.boolean(),
}),
})
.responseOf({
schema: z.object({
id: z.string(),
name: z.string(),
}),
})
.build({
id: "fetch_user",
method: "get",
path: "/users/me",
});

Query and body validation runs before the request is sent. Response validation runs after the backend response is parsed. Validation failures reject with a RequestError whose code identifies the failing part, such as validation/query-validate-error or validation/response-validate-error.

Body encoding

Use the encoding option with bodyOf when the server expects a non-JSON body:

const submitForm = API
.endpoint()
.bodyOf<{ name: string }>({ encoding: "application/x-www-form-urlencoded" })
.responseOf<{ accepted: boolean }>()
.build({
id: "submit_form",
method: "post",
path: "/forms",
});

Supported encodings are application/json, application/x-www-form-urlencoded, and multipart/form-data. Multipart arrays and nested objects are expanded into indexed and dotted field names, and Blob, ArrayBuffer, and typed-array values are converted to file parts when supported by the runtime.

State validation

State is local request context intended for middleware. It is not sent to the server:

const request = API
.endpoint()
.stateOf({ schema: z.object({ requestId: z.string() }) })
.build({ id: "request", method: "get", path: "/request" });

await request.submit({ state: { requestId: "request-123" } });

Passing a schema directly to queryOf, bodyOf, responseOf, or stateOf is supported for compatibility but deprecated. Prefer { schema }.