Calling the tRPC API
The HTTP wire format for every /trpc procedure.
All 40+ domain routers are served over plain HTTP at
https://api.rekamedika.com/trpc/{procedure} — no tRPC client required. Every
procedure page in the API Reference has an interactive playground; this page
explains the envelope.
Wire format
The input object is URL-encoded JSON in the input query parameter:
curl -G https://api.rekamedika.com/trpc/pasien.list \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--data-urlencode 'input={"page":1,"size":20,"keyword":"budi"}'Omit input entirely when the procedure takes no (or optional) input.
The input object is the JSON body:
curl -X POST https://api.rekamedika.com/trpc/pasien.create \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"nama":"Budi Santoso","tglLahir":"1990-01-31","jenisKelamin":"L"}'Response envelope
{ "result": { "data": { "…": "procedure output" } } }Errors use the tRPC error envelope; stack traces are stripped server-side:
{
"error": {
"message": "Tenant context required",
"code": -32001,
"data": { "code": "UNAUTHORIZED", "httpStatus": 401, "path": "pasien.list" }
}
}Rules that apply to every procedure
- Tenant scoping — results are filtered to the tenant of the
authenticated user. Only a superadmin session may act on another tenant
(via the
x-tenant-codeheader); OAuth Bearer callers and all other roles are always pinned to their own tenant. - Scopes (Bearer callers) — queries need
simrs:read, mutations needsimrs:write. - RBAC (mutations) — mutations are gated by
requireRoles(...)server-side;superadminalways passes, other roles vary per domain. Every gated mutation writes an audit-log row in the same transaction. - Validation — inputs are zod-validated; the schemas shown in the API Reference are generated from those validators.
TypeScript clients
Inside the monorepo, clients import the router type directly
(import type { AppRouter } from "@rekamedika/api/routers/index") and get
end-to-end types without codegen.
Is this page helpful?