Call Your API
The SDK from the last chapter is just TypeScript — anything that imports TypeScript can use it. This chapter walks through three real consumption patterns: a Node script, a React component, and an error case.
1. Set up the connection
Every SDK call takes an IConnection as its first argument. Build it once:
import { IConnection } from "@my-app/api"; // or "../api"
export const connection: IConnection = {
host: "http://localhost:37001",
};Add headers when you need auth:
const authed: IConnection = {
...connection,
headers: { Authorization: `Bearer ${token}` },
};IConnection is a plain object. You can build it from environment variables, swap it per test, or wrap it in a custom hook — there is no global state.
2. A Node script
Drop this in a scripts/ directory and run it with npx ttsx scripts/probe.ts. (ttsx is the Nestia toolchain’s TypeScript runner — think ts-node or tsx, but with Nestia’s transformer applied. If you prefer, run npx ttsc to compile first and then node scripts/probe.js.)
import api from "@my-app/api";
import { connection } from "../connection";
const main = async () => {
const created = await api.functional.articles.create(connection, {
title: "Hello SDK",
body: "First article via the generated client.",
});
console.log("Created:", created.id);
const read = await api.functional.articles.at(connection, created.id);
console.log("Read back:", read.title);
};
main().catch(console.error);Try changing title: "no" (too short). TypeScript will not complain — the length is a runtime tag — but the server will return a 400 and the SDK throws an HttpError. We will handle that in section 4.
3. A React component
The exact same import works in a Vite / Next.js / React Native client:
import api from "@my-app/api";
import { useState } from "react";
import { connection } from "./connection";
export const CreateArticleForm = () => {
const [title, setTitle] = useState("");
const [body, setBody] = useState("");
const [out, setOut] = useState<string | null>(null);
const submit = async () => {
const article = await api.functional.articles.create(connection, {
title,
body,
});
setOut(article.id);
};
return (
<form onSubmit={(e) => { e.preventDefault(); void submit(); }}>
<input value={title} onChange={(e) => setTitle(e.target.value)} />
<textarea value={body} onChange={(e) => setBody(e.target.value)} />
<button>Create</button>
{out && <p>Created: {out}</p>}
</form>
);
};What you get for free:
- Autocomplete on
article.id,article.title, etc. - Rename refactors that follow through from server to client. Rename
IArticle.titleon the server, runnpx nestia sdk, and the frontend stops compiling at the exact line that needs to change. - No URL strings. No
Content-Typeheaders. NoJSON.stringify. The SDK does it all.
Bundling the SDK for the browser? TypeScript compilers handle the SDK directly with no special config. If you do not call typia.assert in your frontend code, you don’t even need a Nestia plugin in your bundler. If you do, install @ttsc/unplugin — see Setup → Bundlers.
4. Handle errors
The SDK throws HttpError for any non-2xx response:
import api, { HttpError } from "@my-app/api";
try {
await api.functional.articles.create(connection, {
title: "no", // too short
body: "",
});
} catch (e) {
if (e instanceof HttpError) {
console.log(e.status); // 400
console.log(await e.toJSON()); // { path: "$input.title", expected: "...", value: "no" }
} else {
throw e;
}
}Advanced: typed error responses. For richer error handling — e.g. a 400 that returns a validation DTO and a 403 that returns a permission DTO, each fully typed — flip propagate: true in nestia.config.ts. The SDK then returns a { success, status, data } discriminated union instead of throwing, so the client can branch on the status code with type narrowing. See SDK → Propagation Mode when you’re ready.
5. What you’ve earned
The frontend talks to the backend with the same types the backend stores. A breaking change in a DTO is now a compile error, not a 2 a.m. Slack thread. That is the point of the whole exercise.
Next
Two more generators are waiting: Generate Swagger for an OpenAPI document, then Auto E2E Tests for a free regression suite.