API Methods
Make schema-validated GET, POST, PUT, PATCH, and DELETE requests with the api method helpers.
api.get, api.post, api.put, api.patch, and api.delete are HTTP method helpers bound to $fetch. Use them when the HTTP method is known up front and the response should be validated.
import { api } from "@zap-studio/fetch";
Methods
| Method | HTTP method |
|---|---|
api.get |
GET |
api.post |
POST |
api.put |
PUT |
api.patch |
PATCH |
api.delete |
DELETE |
Each helper has the same overloads, options, and error behavior as $fetch, but injects its HTTP method for you. The injected method always wins — a method passed in options is overridden.
Read Data
import { api } from "@zap-studio/fetch";
import { z } from "zod";
const UserSchema = z.object({
id: z.string(),
name: z.string(),
});
const user = await api.get("https://api.example.com/users/1", UserSchema);
Send JSON
Use the json option for JSON request bodies. It is stringified with JSON.stringify and gets Content-Type: application/json when no content type is already set.
import { api } from "@zap-studio/fetch";
import { z } from "zod";
const CreateUserResponseSchema = z.object({
id: z.string(),
name: z.string(),
});
const user = await api.post("https://api.example.com/users", CreateUserResponseSchema, {
json: {
name: "Ada",
},
});
CreateUserResponseSchema validates the response from the server. The json object is only the outgoing request body.
Use Native Body
Use native body when sending FormData, Blob, ReadableStream, or an already-serialized payload.
import { api } from "@zap-studio/fetch";
import { z } from "zod";
const ProfileSchema = z.object({
id: z.string(),
avatarUrl: z.string(),
});
const avatarBytes = new Uint8Array([137, 80, 78, 71]);
const avatar = new Blob([avatarBytes], { type: "image/png" });
const formData = new FormData();
formData.set("avatar", avatar, "avatar.png");
const profile = await api.patch("https://api.example.com/profile", ProfileSchema, {
body: formData,
});
body and json cannot be used together — providing both throws a TypeError.
Query Params
searchParams accepts the same inputs as new URLSearchParams(...).
import { api } from "@zap-studio/fetch";
import { z } from "zod";
const UserListSchema = z.array(z.object({ id: z.string(), name: z.string() }));
const page = await api.get("https://api.example.com/users", UserListSchema, {
searchParams: {
page: "1",
limit: "20",
},
});
Non-Throw Modes
HTTP errors and validation issues throw by default. You can disable either behavior per request.
import { api } from "@zap-studio/fetch";
import { z } from "zod";
const UserSchema = z.object({ id: z.string(), name: z.string() });
// Does not throw FetchError on non-2xx responses
const user = await api.get("https://api.example.com/users/missing", UserSchema, {
throwOnFetchError: false,
});
// Returns a Standard Schema result object instead of throwing ValidationError
const result = await api.get("https://api.example.com/users/1", UserSchema, {
throwOnValidationError: false,
});
if (result.issues) {
console.error(result.issues);
} else {
console.log(result.value);
}
See Validation for details on the result object shape.
Raw Responses
The method helpers mirror the $fetch overloads, so calling one without a schema returns the native Response:
import { api } from "@zap-studio/fetch";
const response = await api.delete("https://api.example.com/sessions/current");
console.log(response.status);
For clarity, prefer $fetch directly when raw response handling is the main goal.