Call the API from a Script
This guide calls the tRPC Platform API from a standalone Node or Bun script. It
covers getting a token, a raw fetch version (to see the superjson wire format), the typed
@trpc/client version, paginating a list, and handling the error envelope.
Get a token
Programmatic callers authenticate with a session JWT in the Authorization header:
Authorization: Bearer <session JWT>
The token is the HS256 session JWT (signed with AUTH_SECRET) — the same value the
__Secure-authjs.session-token cookie carries. Keep it out of source; read it from the
environment:
export INKLURA_TOKEN="<session JWT>"
Verify it resolves before doing real work by calling auth.getSession (shown below).
Raw fetch
Useful for seeing the wire format. Queries are GET with the input URL-encoded into
?input={"json":<value>}; mutations are POST with the body {"json":<value>}. The result
is nested at result.data.json.
const BASE = "https://manage.inklura.fr/api/trpc";
const auth = { Authorization: `Bearer ${process.env.INKLURA_TOKEN}` };
// Query (GET): who am I?
const input = encodeURIComponent(JSON.stringify({ json: {} }));
const meRes = await fetch(`${BASE}/auth.getSession?input=${input}`, {
headers: auth,
});
const me = (await meRes.json()).result.data.json;
console.log("session:", me);
// Mutation (POST): create a client
const createRes = await fetch(`${BASE}/clients.create`, {
method: "POST",
headers: { ...auth, "Content-Type": "application/json" },
body: JSON.stringify({ json: { name: "Acme SARL", email: "contact@acme.example" } }),
});
const created = (await createRes.json()).result.data.json;
console.log("created:", created.id);
For a procedure that takes no input you can omit ?input= entirely.
Typed @trpc/client
For a TypeScript caller, @trpc/client handles the superjson wrapping and batching for you.
Configure the superjson transformer on an httpBatchLink and set the Authorization
header there:
import { createTRPCClient, httpBatchLink } from "@trpc/client";
import superjson from "superjson";
const client = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: "https://manage.inklura.fr/api/trpc",
transformer: superjson,
headers() {
return {
Authorization: `Bearer ${process.env.INKLURA_TOKEN}`,
// Optionally pin tenant / site scope:
"X-Tenant-Id": process.env.INKLURA_TENANT_ID ?? "",
"X-Site-Id": process.env.INKLURA_SITE_ID ?? "",
};
},
}),
],
});
const session = await client.auth.getSession.query();
const created = await client.clients.create.mutate({
name: "Acme SARL",
email: "contact@acme.example",
});
With the transformer configured, you pass and receive plain values — no manual
{"json":…} wrapping. See tRPC Procedures for the calling conventions and
batching details.
Paginate a list
List procedures follow the { page, pageSize } convention and return
{ items, total, page, pageSize }. Walk every page:
async function listAllProducts() {
const all = [];
let page = 1;
const pageSize = 50;
for (;;) {
const res = await client.products.list.query({ page, pageSize });
all.push(...res.items);
if (all.length >= res.total || res.items.length === 0) break;
page += 1;
}
return all;
}
Pagination is a convention rather than a framework guarantee — confirm the shape for the procedure you call. See Pagination & Filtering.
Handle errors
Failures come back as the standard tRPC error envelope; the useful fields are under
error.data (code, httpStatus), and Zod validation failures add data.zodError. The
typed client throws a TRPCClientError whose data carries them:
import { TRPCClientError } from "@trpc/client";
try {
await client.clients.create.mutate({ name: "", email: "not-an-email" });
} catch (err) {
if (err instanceof TRPCClientError) {
const data = err.data; // { code, httpStatus, ... }
console.error(data?.code, data?.httpStatus);
if (data?.zodError) {
console.error("field errors:", data.zodError.fieldErrors);
}
} else {
throw err;
}
}
With raw fetch, read the same fields off the parsed body's error.data instead. See
Errors & Rate Limits for the code-to-status mapping and the zodError shape.
Related
- tRPC Procedures — calling conventions, batching, router catalog
- Errors & Rate Limits — the error envelope and Zod errors
- Pagination & Filtering — the
page/pageSizeconvention