SDK
createBrandfineClient
The SDK's entry point. Typed HTTP client over the /external/* surface.
import { createBrandfineClient } from '@brandfine/client'
const bf = createBrandfineClient({
baseUrl: 'https://api.brandfine.co',
apiKey: process.env.BRANDFINE_API_KEY!,
})Returns a stateless, multi-instance-safe handle. Construct one
per (baseUrl, apiKey) pair — multi-tenant consumers create
several side-by-side.
Options
| Option | Type | Required | Notes |
|---|---|---|---|
baseUrl | string | ✓ | No trailing slash (the client trims one if present). |
apiKey | string | ✓ | Workspace-scoped key. |
fetch | typeof fetch | — | Override for tests / edge runtimes / tracing wrappers. |
userAgent | string | — | Defaults to @brandfine/client. |
Empty baseUrl or apiKey throws at construction — fail loud,
not silent.
Methods
bf.posts.list({ type, locale, forceLimit }) // paginated, returns flat array
bf.posts.getBySlug(slug) // null on 404
bf.workspace.get<TCustom, TSchema>() // narrow customConfig + schemaOrg
bf.navigations.get(key) // null on 404
bf.categories.list({ locale })
bf.get<T>(path, opts?) // escape hatch for new endpointsError handling
Non-2xx responses (except 404 on nullable404 endpoints) throw
BrandfineApiError:
import { BrandfineApiError } from '@brandfine/client'
try {
await bf.posts.list()
} catch (err) {
if (err instanceof BrandfineApiError) {
console.error(err.status, err.statusText, err.body, err.url)
if (err.status === 429) await sleep(1000) // backoff
}
throw err
}Typed customConfig
When you have a known shape for customConfig (per post type),
parameterize the methods:
type ServiceConfig = {
apply: { visaSlug: string; destinationCode: string } | null
faq: Array<{ question: string; answer: string }>
}
const services = await bf.posts.list<ServiceConfig>({ type: 'services' })
// services[0].customConfig is now typed as ServiceConfig | nullThe default is unknown — opt into typing incrementally as the
consumer's needs solidify.