ehsan.blog
~/blog/api-client-part-18-full-api-reference — zsh
cat api-client-part-18-full-api-reference.md

The api-client cheat sheet: every config option and method in one place

·3 min read

Everything else in this series explains why a feature works the way it does. This post skips the why — it’s the reference I actually want open in a second tab while I’m writing config, not something meant to be read top-to-bottom. Each section links conceptually back to the post that covers the reasoning, if you need it.

createClient(config)

KeyTypeCovered in
baseURLstringPart 2
openapi.mode'runtime' | 'codegen'Parts 2, 11
openapi.validateResponsesbooleanPart 12
openapi.onValidationFailure'warn' | 'throw'Part 12
auth.strategy'bearer' | 'cookie' | 'apiKey' | 'oauth2'Part 5
http.timeoutnumber (ms)Parts 4, 7
http.retry.attemptsnumberPart 7
http.retry.backoff'exponential' | 'linear'Part 7
http.retry.retryOnnumber[] (status codes)Part 7
cache.strategy'cache-first' | 'network-first' | 'stale-while-revalidate'Part 6
cache.ttlnumber (ms)Part 6
concurrency.maxnumberPart 7
tenancy.getTenantId() => string | Promise<string>Part 8
environmentsRecord<string, { baseURL: string }>Part 8
envstringPart 8
safeModebooleanPart 9
hooks.beforeRequest(config) => configPart 10
hooks.afterResponse(response) => responsePart 10
hooks.onError(error) => void | anyPart 10
modulesRecord<string, ModuleDefinition>Part 2

defineModule({ config, methods })

Module-level config accepts the same keys as createClient’s baseURL, timeout, headers, auth, cache, retry, tenancy, validation — overriding the global value for every method in that module. See Part 3 and Part 4 for the merge order.

ts
defineModule({
  config: { timeout: 20_000 },
  methods: {
    methodName: async (ctx, ...args) => ctx.request({ /* spec */ }),
  },
})

ctx.request(spec, perCall?)

spec:

KeyTypeNotes
method'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
pathstring{placeholders} for path params
pathParamsRecord<string, string>Required if path has placeholders
queryRecord<string, unknown>
bodyunknown

perCall (PerCallConfig):

KeyTypeCovered in
signalAbortSignalPart 7
headersRecord<string, string>Part 4
tenantIdstringPart 8
cache.enabledbooleanPart 6
cache.ttlnumberPart 6
cache.bustbooleanPart 6
retry.attemptsnumberPart 7
timeoutnumberPart 4
skipAuthbooleanPart 5
skipDedupbooleanPart 7
safeModebooleanPart 9
responseType'json' | 'blob' | 'text' | 'arraybuffer'

Returns ApiResponse<T>:

ts
{ data: T, status: number, statusText?: string, headers: Record<string, string>, fromCache?: boolean }

See Part 3.

Error classes

ClassThrown whenCovered in
ApiErrorBase class for all API errorsPart 9
NetworkErrorNo response at all (offline, DNS)Part 9
TimeoutErrorRequest exceeded timeout, after retries exhaustedParts 7, 9
ValidationError4xx with structured error bodyPart 9
AuthError401/403, or refresh failureParts 5, 9
ConfigurationErrorYour code called the client wrongPart 9

Cache methods

ts
ctx.cache.invalidate(key: string): Promise<void>
ctx.cache.invalidatePattern(pattern: string): Promise<void>

See Part 6.

Events (api.on(event, handler))

EventPayloadCovered in
request:start{ key }Part 10
request:end{ key, status }Part 10
cache:hit{ key }Parts 6, 10
cache:miss{ key }Part 6
cache:invalidate{ pattern }Part 6
retry{ attempt, key }Part 7
auth:refreshPart 5

Codegen CLI commands

CommandPurposeCovered in
generate --spec --outGenerate types + descriptors oncePart 11
watch --spec --outRegenerate on save, local devPart 11
validate --specCheck spec well-formednessPart 11
diff --old --newCategorize spec changes as breaking/non-breakingPart 11
drift-check --spec --baseURLCompare live backend against committed specPart 12

RPC bridge

ts
// server
createRpcHandler(realClient, { expose: { moduleName: ['methodName'] } })

// browser
createRpcClient({ endpoint: '/api/rpc' })

Deny-by-default: only { module, method } pairs listed in expose are reachable. See Parts 14–15 for the full architecture and security model.

TanStack Query integration

ts
useApiQuery(api.module.method, [args])
useApiMutation(api.module.method, { invalidates: [api.otherModule.otherMethod] })

Available for React, Vue, and Solid, with identical key-generation semantics. See Part 13.

Testing

ts
createMockClient({
  moduleName: { methodName: async (...args) => mockReturnValue },
})

See Part 17.

What this post is for

Not a takeaway section this time — this whole post is the takeaway from the series so far, compressed. If a row here doesn’t make sense on its own, that’s exactly what the linked post is for.

Next: troubleshooting and FAQ — the errors I’ve actually hit using this package, told as the debugging stories they actually were.

  • developerehsan
ls ./related
cat ./comments

Comments are not configured yet. Enable GitHub Discussions and paste the giscus repo-id / category-id into src/consts.ts.