TypeScript client
One generated file, no dependencies. curl it and start calling.
A typed TypeScript client, generated from the same registry the router dispatches on. One file, no dependencies, no build step, no version to pin.
curl https://app.360nook.com/api/v1/client.ts > nook.ts
import { Nook, NookError } from "./nook";
const nook = new Nook(process.env.NOOK_API_KEY!);
const { data } = await nook.listContacts();
await nook.createContact(
{ email: "[email protected]", first_name: "Ana" },
// Same key on a retry returns the original response instead of a
// second contact. One key per operation, not per attempt.
{ idempotencyKey: "signup-8f3a" },
);
await nook.bookAppointment({
calendar_id: "...",
starts_at: "2026-09-10T10:00:00Z",
contact_id: "...",
});Errors carry their reason
A non-2xx throws a NookError that keeps what the API said, rather than flattening it to “request failed”.
try {
await nook.createContact({ first_name: "Ana" });
} catch (e) {
if (e instanceof NookError) {
e.code; // "invalid_body"
e.fields; // every invalid field at once, not one per round trip
e.requestId; // quote this to support and we find your exact request
}
}Regenerated on every request from the endpoint registry, so it cannot describe an endpoint that does not exist. If we add one, re-run the curl.
Works anywhere fetch does — Node 18+, Deno, Bun, Workers. It runs in a browser too, but a key in a browser is a key you have given away; use OAuth there.