Typed clients
Generate a typed API client from the Chronicler OpenAPI document. One generator per language keeps the models and calls in step with the server, so you never hand-write a request.
The Chronicler API ships a full OpenAPI 3 document. Do not hand-write requests or model types. Point a generator at the document, and it produces typed models and one function per operation for your language. When the API changes, you regenerate, and your compiler shows you every call that moved.
The code samples across these docs, such as the one in Quickstart, call a generated client of this kind.
The OpenAPI document
Every Chronicler server serves its own document. Use it as the generator input.
- Hosted:
https://api.chronicler.one/openapi.json - Self-hosted or local:
http://127.0.0.1:7777/openapi.json
The document names each operation with a stable operationId, such as relationship.create. Every generator turns that id into the function or method name, so the names stay predictable across languages.
Generate against a running server
The document is served by the API, not committed to a repository. Start the server first, then point the generator at its URL. A CI job that regenerates the client starts the server, or reads a document you export in a build step.
TypeScript (Node & Bun)
Use Orval, just like we do in the frontend application. It reads the document and writes typed fetch functions plus their models.
Generate the TypeScript client
- Add Orval as a dev dependency.
- Write
orval.config.tswith the document URL and the output paths. - Add the mutator file that sets the base URL and the bearer token.
- Run
bunx orvalto write the client. Rerun it after any API change.
The generator writes one function per operation, named from the operationId. So relationship.create becomes relationshipCreate, and it takes the typed body and returns the typed result.
import { relationshipCreate } from "./api-client/endpoints/chronicler"
await relationshipCreate(chronicleId, {
from: "res_01jq8p9k7mf4rb2xn0z9v6t3wy",
type: "rel_ally_of",
to: "res_01jqb2m5x8k7wr4n0z9v6t3sya",
})
Go
Use oapi-codegen. It reads the document and writes a typed client with the request and response models. It is the closest Go match to the Orval setup, since both give you typed models and a thin client with no runtime reflection.
Generate the Go client
- Add oapi-codegen as a tool dependency with
go get -tool. - Write
config.yamlwith the package name and what to generate. - Add a
//go:generatedirective that points at the document URL. - Run
go generate ./...to writeclient.gen.go. Rerun it after any API change.
The generator writes one method per operation on a ClientWithResponses, named from the operationId. So relationship.create becomes RelationshipCreate, and it takes a typed body and a context.
client, err := chronicler.NewClientWithResponses("https://api.chronicler.one")
if err != nil {
return err
}
_, err = client.RelationshipCreate(ctx, chronicleID, chronicler.CreateRelationshipBody{
From: "res_01jq8p9k7mf4rb2xn0z9v6t3wy",
Type: "rel_ally_of",
To: "res_01jqb2m5x8k7wr4n0z9v6t3sya",
})
if err != nil {
return err
}
A fully typed alternative
For a spec-first client with strict validation and no reflection, use ogen. It generates a complete typed client and server from the same document. Prefer oapi-codegen for a lighter client that drops into an existing HTTP setup.
Python
Use openapi-python-client. It writes a typed package with dataclass models and one module per operation.
Generate the Python client
- Run the generator against the document URL.
- Import the operation module and its typed model.
- Build the client with the base URL and the bearer token.
- Call the operation. Regenerate after any API change.
Authenticating the client
Every call carries a bearer token in the Authorization header. See Authentication for how to get one, and Service accounts & tokens for a machine identity.
Set the token in one place, not on every call.
- TypeScript: add it in the Orval mutator, so
customFetchattaches it to every request. - Go: pass a request editor to
NewClientWithResponsesthat sets the header. - Python: pass it in the
Clientheaders, as shown above.
Where to go next
- Try a first call in Quickstart.
- Read Authentication to get a token.
- Create a machine identity in Service accounts & tokens.