Beta You're reading the docs for Kubb v5, which is currently in beta. View the stable v4 docs
Skip to content

Set your own baseURL

The generated client prepends a baseURL to every request, so it needs to know which host to call. Set your own when the spec carries no usable server URL, when you target a different host per environment (local, staging, production), or when the host depends on the running app, such as the tenant the user signed in as.

Set it at build time or at runtime. At build time you read it from the servers list in your OpenAPI spec or pass the baseURL option to the client plugin, and it bakes into the generated code. At runtime you set it on the generated client, which suits a value you only know once the app runs, such as an environment variable or the signed-in tenant.

Read it from the spec

When you set no baseURL on the client plugin, the client falls back to the server URL the OpenAPI adapter resolves. The adapter resolves one only when you point its server.index at an entry in the spec's servers array, so set adapter: adapterOas({ server: { index: 0 } }) to use the first entry. Add variables to fill in any {variable} placeholders in the chosen URL. Leave server unset and the spec contributes no baseURL.

yaml
openapi: 3.0.3
info:
  title: Swagger Example
  description:
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.0
servers:
  - url: http://petstore.swagger.io/api
  - url: http://localhost:3000
typescript
import {  } from 'kubb'
import {  } from '@kubb/adapter-oas'
import {  } from '@kubb/plugin-axios'

export default ({
  : {
    : './petStore.yaml',
  },
  : {
    : './src/gen',
  },
  : ({ : { : 0 } }),
  : [()],
})

defineConfig applies adapterOas() for you, so you set adapter only to change an adapter option. Here it sets server.index so the adapter resolves http://petstore.swagger.io/api from the spec.

Use the baseURL option

Pass baseURL to the client plugin. It prepends the URL to every request.

typescript
import {  } from 'kubb'
import {  } from '@kubb/plugin-axios'
import {  } from '@kubb/plugin-react-query'

export default ({
  : {
    : './petStore.yaml',
  },
  : {
    : './src/gen',
  },
  : [
    ({
      : 'https://localhost:8080/api/v1',
    }),
    ({
      : 'axios',
    }),
  ],
})

Set it at runtime

The baseURL rides the same ClientConfig as auth and the transport, so you set it at runtime the same three ways. Pick the one that matches the scope you need.

Call client.setConfig({ baseURL }) to point the whole app at one URL. Every generated function imports the shared client, so the change reaches each call at once. This fits reading the URL from an environment variable on startup:

typescript
import { client } from './gen/clients/.kubb/client'

client.setConfig({ baseURL: import.meta.env.VITE_API_URL })

Call createClient({ baseURL }) for an isolated client with its own URL, which fits a multi-tenant app or talking to more than one backend. Pass it on the client option of a call, or hand it to a query plugin:

typescript
import { createClient } from './gen/clients/.kubb/client'
import { getPetById } from './gen/clients/getPetById'

const staging = createClient({ baseURL: 'https://staging.petstore.swagger.io/v2' })

const { data } = await getPetById({ path: { petId: 1 }, client: staging })

Pass baseURL on a single call to override the client for that one request:

typescript
import { getPetById } from './gen/clients/getPetById'

const { data } = await getPetById({ path: { petId: 1 }, baseURL: 'https://localhost:3000' })

A baseURL set on the call wins over createClient, which wins over setConfig, which wins over the build-time value.

Rewrite the URL with an interceptor

A request interceptor sees the final request before it is sent, so it can rewrite the URL per call from logic the static options cannot express, such as routing a path to a different host:

typescript
import { client } from './gen/clients/.kubb/client'

client.interceptors.request.use((request) => {
  if (request.url.startsWith('/admin')) {
    request.url = `https://admin.petstore.swagger.io${request.url}`
  }
  return request
})

The interceptor receives the URL already built from the resolved baseURL, so reach for it only when the host depends on the request. For a fixed URL, setConfig and createClient stay the simpler path. See the interceptors guide for the full request, response, and error channels.

See also