Top-level methods
Reference for board context, SEO infrastructure, the raw client, and shared response conventions.
A
JThe SDK has public Board reads and one raw request escape hatch. Namespace methods use the same underlying BoardClient pipeline.
board.context()
1context(options?: FetchOptions): Promise<PublicBoard>
Returns the public configuration needed to build the board shell:
| Field | Use |
|---|---|
id, slug, name | Board identity. id is immutable; slug can change. |
language | Required input for SDK display-formatting helpers. |
logoUrl, icons | Board logo and the favicon / app-icon pack derived from it (absolute URLs or null). Brand identity — map icons into root-layout <link rel="icon"> tags. |
primaryDomain, showCavunoBranding | Public domain and whitelabel state. |
features | Capability gates for alerts, candidates, employers, blog, talent directory (off | public | employers_only), registration wall, password protection, public submission, paywall, and impressum. |
analytics | Public analytics IDs and the cookie-consent requirement. |
customFields, contact | Job-field definitions (keyed by model) and public contact/social identity. |
sandbox | Platform sandbox marker. Only doctor’s opted-in write probes should use it. |
12345const context = await board.context({ cache: 'force-cache' });if (context.features.blog) {// Register or render the public blog route.}
Context is public and can normally use a shared cache. Feature flags guide presentation; they do not replace API authorization or entitlement enforcement.
board.seo()
1seo(options?: FetchOptions): Promise<BoardSeo>
Returns public platform infrastructure configuration:
canonicalBasefor canonical links and therobots.txtsitemap line.adsTxtandindexNowKey, each nullable.googleSiteVerification, nullable.manifest.name(board display name for a web manifest).
Icon URLs and themeColor are not returned — applications ship their own brand assets and presentation tokens.
123456789const seo = await board.seo({ cache: 'force-cache' });export function adsTxtResponse() {if (seo.adsTxt === null) return new Response('Not found', { status: 404 });return new Response(seo.adsTxt, {headers: { 'content-type': 'text/plain; charset=utf-8' },});}
board.seo() does not create page metadata or JSON-LD. Those pure builders live in @cavuno/board/seo.
Make a request to a custom endpoint
Use board.client.fetch() when an endpoint does not yet have a namespace method.
1fetch<T>(path: string, options?: FetchOptions): Promise<T>
Use the raw client for a live board-relative endpoint that does not yet have a namespace method. Prefer namespace methods when available because their bodies, queries, and responses are generated from the API contract.
123456789interface BoardStats {object: 'board_stats';activeJobs: number;}const stats = await board.client.fetch<BoardStats>('/custom/stats', {query: { period: '30d' },signal: AbortSignal.timeout(5_000),});
The path is appended below /v1/boards/{identifier}. It must begin with / to produce the intended route. The generic type is an application assertion—the raw client does not validate the response at runtime.
Query behavior
Queries must be flat objects. Arrays serialize as repeated keys, preserving order:
123456789await board.client.fetch('/custom/jobs', {query: {remoteOption: ['remote', 'hybrid'],cursor: null,limit: 20,},});// ?remoteOption=remote&remoteOption=hybrid&limit=20
null and undefined are omitted. Other values are converted with String(value). Nested objects are not recursively encoded.
Body and response behavior
- Ordinary bodies are JSON-stringified and receive
content-type: application/json. - Strings,
URLSearchParams,FormData,Blob,ArrayBuffer, andReadableStreamare sent unchanged. - A successful HTTP 204 resolves to
undefinedwithout parsing. - Other successful responses are parsed as JSON.
- Every non-2xx response throws
BoardApiError; an invalid or non-JSON error body becomesunknown_error. - There is no automatic retry, response validation, or 401 refresh.
Shared list envelopes
List methods return ListEnvelope<T> and searches return SearchEnvelope<T>:
123456const page = await board.jobs.list({ limit: 20 });page.object; // "list"page.data; // PublicJobCard[]page.hasMore; // booleanpage.nextCursor; // string | null
Jobs catalog envelopes can also contain count, limit, offset, and gatedCount. Consumers must ignore unknown additive response fields. Echo nextCursor instead of inspecting it; it is opaque.
Verify the behavior
Use a deliberate 204 endpoint and a deliberate missing path in development. Confirm that the first resolves undefined, while the second throws BoardApiError and retains its status, code, raw envelope, and request ID.