From 2fce77410ce61a9a328be5bcdcedac4d6ed1b6ad Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:53:34 +0000 Subject: [PATCH 1/3] docs: add server URL templating documentation to SDK design section Co-Authored-By: naman.anand@buildwithfern.com --- .../sdks/guides/server-url-templating.mdx | 232 ++++++++++++++++++ fern/products/sdks/sdks.yml | 3 + 2 files changed, 235 insertions(+) create mode 100644 fern/products/sdks/guides/server-url-templating.mdx diff --git a/fern/products/sdks/guides/server-url-templating.mdx b/fern/products/sdks/guides/server-url-templating.mdx new file mode 100644 index 000000000..55608eb91 --- /dev/null +++ b/fern/products/sdks/guides/server-url-templating.mdx @@ -0,0 +1,232 @@ +--- +title: Server URL templating +description: Configure server URL templating in Fern SDKs to support dynamic base URLs with variables like region and environment. +--- + +Server URL templating lets you define base URLs with variable placeholders (e.g., `{region}`, `{environment}`) that SDK users can customize at runtime. This is useful for APIs deployed across multiple regions, environments, or custom domains. + +Fern reads the standard OpenAPI `servers` block and generates SDK clients that accept these variables, falling back to sensible defaults when they are not provided. + +## Configuring in OpenAPI + +Define server variables inside the top-level `servers` block of your OpenAPI spec. Each variable can include a `default` value and an optional `enum` of allowed values. + +Use the `x-fern-default-url` extension to provide a static fallback URL that the SDK uses when no variables are supplied. + +```yaml {7-8, 10} title="openapi.yml" +openapi: 3.0.3 +info: + title: My API + version: 1.0.0 +servers: + - url: https://api.{region}.{environment}.example.com/v1 + description: Regional API server + x-server-name: Default + x-fern-default-url: https://api.example.com/v1 + variables: + region: + default: us-east-1 + enum: + - us-east-1 + - us-west-2 + - eu-west-1 + environment: + default: prod + enum: + - prod + - staging + - dev +``` + +### Key fields + +| Field | Description | +|-------|-------------| +| `url` | The URL template with `{variable}` placeholders. | +| `variables` | A map of variable names to their `default` value and optional `enum` of allowed values. | +| `x-fern-default-url` | A static URL the SDK falls back to when no variables are provided. | +| `x-server-name` | A human-readable name for the server entry used in the generated environments enum. | + +## Multiple base URLs + +Different endpoints can target different servers. For example, your main API and auth service may live at separate domains. Add a `servers` block directly on an endpoint to override the top-level server for that path. + +Use `x-fern-server-name` to give each endpoint-level server a distinct name so Fern can group them correctly. + +```yaml {5-6, 8} title="openapi.yml" +paths: + /auth/token: + post: + servers: + - url: https://auth.{region}.example.com + x-fern-server-name: Auth + x-fern-default-url: https://auth.example.com + variables: + region: + default: us-east-1 + enum: + - us-east-1 + - us-west-2 + - eu-west-1 +``` + +When Fern detects multiple named servers, the generated SDK client resolves each endpoint to the correct base URL automatically. + +## Generated SDK behavior + +Fern generates an environments module that exposes the default URLs for each named server. SDK users can select a pre-defined environment or pass custom URL strings. + + + + +The generated SDK exposes an `environments` object and an `environment` client option: + +```typescript title="environments.ts" +export interface MyApiEnvironmentUrls { + base: string; + auth: string; +} + +export const MyApiEnvironment = { + RegionalApiServer: { + base: "https://api.example.com/v1", + auth: "https://auth.example.com", + }, +} as const; +``` + +SDK users can override the base URL at the client or request level: + +```typescript +import { MyApiClient } from "my-api"; + +// Use the default environment +const client = new MyApiClient(); + +// Or provide a custom base URL +const client = new MyApiClient({ + baseUrl: "https://api.us-west-2.staging.example.com/v1", +}); +``` + + + + +The generated SDK exposes an `Environment` class: + +```python title="environment.py" +class MyApiEnvironment: + REGIONAL_API_SERVER = { + "base": "https://api.example.com/v1", + "auth": "https://auth.example.com", + } +``` + +SDK users can override the base URL when constructing the client: + +```python +from my_api import MyApiClient + +# Use the default environment +client = MyApiClient() + +# Or provide a custom base URL +client = MyApiClient( + base_url="https://api.us-west-2.staging.example.com/v1", +) +``` + + + + +The generated SDK uses functional options to configure the base URL: + +```go +import ( + client "github.com/my-org/my-api/client" + option "github.com/my-org/my-api/option" +) + +// Use the default environment +c := client.NewClient() + +// Or provide a custom base URL +c := client.NewClient( + option.WithBaseURL("https://api.us-west-2.staging.example.com/v1"), +) +``` + + + + +The generated SDK exposes an environment enum and a builder method: + +```java +import com.example.api.MyApiClient; + +// Use the default environment +MyApiClient client = MyApiClient.builder().build(); + +// Or provide a custom base URL +MyApiClient client = MyApiClient.builder() + .url("https://api.us-west-2.staging.example.com/v1") + .build(); +``` + + + +## Fern Definition + +If you use the Fern Definition format instead of OpenAPI, configure server URL templating in your `api.yml`: + +```yaml title="api.yml" +environments: + RegionalApiServer: + urls: + Base: https://api.example.com/v1 + Auth: https://auth.example.com + url-templates: + Base: https://api.{region}.{environment}.example.com/v1 + Auth: https://auth.{region}.example.com + default-urls: + Base: https://api.example.com/v1 + Auth: https://auth.example.com + variables: + Base: + - id: region + default: us-east-1 + values: + - us-east-1 + - us-west-2 + - eu-west-1 + - id: environment + default: prod + values: + - prod + - staging + - dev + Auth: + - id: region + default: us-east-1 + values: + - us-east-1 + - us-west-2 + - eu-west-1 +default-environment: RegionalApiServer +``` + +## Language support + +Server URL templating is supported across the following generators: + +| Language | Supported | +|----------|-----------| +| TypeScript | | +| Python | | +| Java | | +| Go | | +| Ruby | | +| .NET | | +| Swift | | +| PHP | | +| Rust | | diff --git a/fern/products/sdks/sdks.yml b/fern/products/sdks/sdks.yml index 00543c91f..a23ad588f 100644 --- a/fern/products/sdks/sdks.yml +++ b/fern/products/sdks/sdks.yml @@ -245,6 +245,9 @@ navigation: - page: Filter endpoints by audience path: ./guides/filter-your-endpoints-audiences.mdx slug: audiences + - page: Server URL templating + path: ./guides/server-url-templating.mdx + slug: server-url-templating - section: Request behavior slug: deep-dives collapsed: true From 6eebf580152aa4b12787ff22be42405ff779d7eb Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 12:01:59 +0000 Subject: [PATCH 2/3] fix: address vale lint - use contraction 'they're' Co-Authored-By: naman.anand@buildwithfern.com --- fern/products/sdks/guides/server-url-templating.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fern/products/sdks/guides/server-url-templating.mdx b/fern/products/sdks/guides/server-url-templating.mdx index 55608eb91..a1349966d 100644 --- a/fern/products/sdks/guides/server-url-templating.mdx +++ b/fern/products/sdks/guides/server-url-templating.mdx @@ -5,7 +5,7 @@ description: Configure server URL templating in Fern SDKs to support dynamic bas Server URL templating lets you define base URLs with variable placeholders (e.g., `{region}`, `{environment}`) that SDK users can customize at runtime. This is useful for APIs deployed across multiple regions, environments, or custom domains. -Fern reads the standard OpenAPI `servers` block and generates SDK clients that accept these variables, falling back to sensible defaults when they are not provided. +Fern reads the standard OpenAPI `servers` block and generates SDK clients that accept these variables, falling back to sensible defaults when they're not provided. ## Configuring in OpenAPI From 5c8063c41e9716ac0f96eee2064cccb9f12c3b70 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 12:14:31 +0000 Subject: [PATCH 3/3] fix: limit language support to Python and Java only Co-Authored-By: naman.anand@buildwithfern.com --- .../sdks/guides/server-url-templating.mdx | 62 +------------------ 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/fern/products/sdks/guides/server-url-templating.mdx b/fern/products/sdks/guides/server-url-templating.mdx index a1349966d..c47867b56 100644 --- a/fern/products/sdks/guides/server-url-templating.mdx +++ b/fern/products/sdks/guides/server-url-templating.mdx @@ -77,39 +77,6 @@ When Fern detects multiple named servers, the generated SDK client resolves each Fern generates an environments module that exposes the default URLs for each named server. SDK users can select a pre-defined environment or pass custom URL strings. - - -The generated SDK exposes an `environments` object and an `environment` client option: - -```typescript title="environments.ts" -export interface MyApiEnvironmentUrls { - base: string; - auth: string; -} - -export const MyApiEnvironment = { - RegionalApiServer: { - base: "https://api.example.com/v1", - auth: "https://auth.example.com", - }, -} as const; -``` - -SDK users can override the base URL at the client or request level: - -```typescript -import { MyApiClient } from "my-api"; - -// Use the default environment -const client = new MyApiClient(); - -// Or provide a custom base URL -const client = new MyApiClient({ - baseUrl: "https://api.us-west-2.staging.example.com/v1", -}); -``` - - The generated SDK exposes an `Environment` class: @@ -137,26 +104,6 @@ client = MyApiClient( ``` - - -The generated SDK uses functional options to configure the base URL: - -```go -import ( - client "github.com/my-org/my-api/client" - option "github.com/my-org/my-api/option" -) - -// Use the default environment -c := client.NewClient() - -// Or provide a custom base URL -c := client.NewClient( - option.WithBaseURL("https://api.us-west-2.staging.example.com/v1"), -) -``` - - The generated SDK exposes an environment enum and a builder method: @@ -217,16 +164,9 @@ default-environment: RegionalApiServer ## Language support -Server URL templating is supported across the following generators: +Server URL templating is currently supported in the following generators: | Language | Supported | |----------|-----------| -| TypeScript | | | Python | | | Java | | -| Go | | -| Ruby | | -| .NET | | -| Swift | | -| PHP | | -| Rust | |