# generators.yml configuration schema

> Complete generators.yml configuration reference for Fern SDK generation. Configure authentication, publishing, GitHub integration, and language-specific settings.

The `generators.yml` file serves two purposes: it declares your API definition (required for OpenAPI/AsyncAPI), and configures SDK generation, including which languages to generate, where to publish them, and how to customize each SDK.

```yaml title="generators.yml" maxLines=10
api:
  specs:
    - openapi: "./openapi.yml"
      namespace: "v1"
      settings:
        title-as-schema-name: true
        inline-path-parameters: false
        respect-forward-compatible-enums: true

whitelabel:
  github:
    username: "my-org"
    email: "sdk@mycompany.com"
    token: "ghp_xxxxxxxxxxxx"

metadata:
  description: "Official SDK for MyAPI"
  authors:
    - name: "SDK Team"
      email: "sdk@mycompany.com"

readme:
  introduction: "Welcome to the MyAPI SDK"
  apiReferenceLink: "https://docs.myapi.com"
  defaultEndpoint:
    method: "GET"
    path: "/users"
  features:
    authentication:
      - "POST /auth/login"
      - "GET /auth/profile"
    users:
      - "GET /users"
      - "POST /users"

default-group: "production"

groups:
  production:
    generators:
      - name: fernapi/fern-typescript-sdk
        version: 0.9.0
      - name: fernapi/fern-python-sdk
        version: 2.0.0
```

## `auth-schemes`

Define authentication methods for your API that your endpoints can reference. Authentication schemes defined in `generators.yml` take precedence over authentication schemes defined in your spec.

Choose from custom headers (API keys), HTTP Basic, Bearer token, or OAuth 2.0 authentication.

<Info>
  Alternatively, you can [define authentication for individual SDKs](#override-api-authentication-settings).
</Info>

```yaml title="generators.yml" maxLines=10
auth-schemes:
  # User-defined scheme name - OAuth with minimal configuration
  simple-oauth:
    scheme: oauth
    type: client-credentials
    get-token:
      endpoint: "auth.token"
    
  # User-defined scheme name - Header auth with custom configuration
  custom-header:
    name: "Custom Auth"
    header: "X-Custom-Auth"
    prefix: "Custom "
    env: "CUSTOM_TOKEN"
    
  # User-defined scheme name - Basic auth
  http-basic:
    scheme: basic
    
  # User-defined scheme name - Bearer token
  jwt-bearer:
    scheme: bearer
```

<AccordionGroup>
  <Accordion title="Header">
    Configure authentication using custom HTTP headers, such as API keys or tokens.

    ```yaml
    auth-schemes:
      api-key: # User-defined scheme name
        name: "API Key Authentication"
        header: "X-API-Key"
        type: "string"
        prefix: "ApiKey "
        env: "MY_API_KEY" # SDK will auto-scan this environment variable
    ```

    <ParamField path="header" type="string" required={true}>
      The name of the HTTP header to use for authentication.
    </ParamField>

    <ParamField path="name" type="string" required={false}>
      A descriptive name for this authentication scheme.
    </ParamField>

    <ParamField path="type" type="string" default="string">
      The type of the header value.
    </ParamField>

    <ParamField path="prefix" type="string" required={false}>
      A prefix to prepend to the header value (e.g., `"Bearer "` or `"Token "`).
    </ParamField>

    <ParamField path="env" type="string" required={false}>
      Environment variable name containing the authentication value. When specified, the generated SDK will automatically scan for this environment variable at initialization.
    </ParamField>
  </Accordion>

  <Accordion title="Basic">
    Configure HTTP Basic authentication using username and password credentials.

    ```yaml
    auth-schemes:
      basic-auth: # User-defined scheme name
        scheme: basic
        username:
          name: "Username"
          env: "BASIC_AUTH_USERNAME" # SDK will auto-scan this environment variable
        password:
          name: "Password"
          env: "BASIC_AUTH_PASSWORD" # SDK will auto-scan this environment variable
    ```

    <ParamField path="scheme" type="'basic'" required={true}>
      Must be set to `"basic"` for Basic authentication schemes.
    </ParamField>

    <ParamField path="username" type="object" required={false}>
      Configuration for the username credential.
    </ParamField>

    <ParamField path="username.name" type="string" required={false}>
      Custom parameter name for the username in the generated SDK. If not specified, defaults to `"username"`. Use this to provide more descriptive or domain-specific parameter names like `"clientId"`, `"userEmail"`, or `"merchantId"`.
    </ParamField>

    <ParamField path="password" type="object" required={false}>
      Configuration for the password credential.
    </ParamField>

    <ParamField path="password.name" type="string" required={false}>
      Custom parameter name for the password in the generated SDK. If not specified, defaults to `"password"`. Use this to provide more descriptive or domain-specific parameter names like `"clientSecret"`, `"apiKey"`, or `"merchantKey"`.
    </ParamField>

    <ParamField path="username.env, password.env" type="string" required={false}>
      Environment variable name that the SDK will automatically scan for the username or password value. When this environment variable is present, users don't need to explicitly provide the username parameter. Follow naming conventions like `YOUR_APP_USERNAME` or `SERVICE_CLIENT_ID`.
    </ParamField>
  </Accordion>

  <Accordion title="Bearer token">
    Configure Bearer token authentication for API access.

    ```yaml
    auth-schemes:
      bearer-token: # User-defined scheme name
        scheme: bearer
        token:
          name: "Access Token"
          env: "BEARER_TOKEN" # SDK will auto-scan this environment variable
    ```

    <ParamField path="scheme" type="'bearer'" required={true}>
      Must be set to `"bearer"` for Bearer token authentication schemes.
    </ParamField>

    <ParamField path="token" type="object" required={false}>
      Configuration for the bearer token.
    </ParamField>

    <ParamField path="token.name" type="string" required={false}>
      A descriptive name for the token.
    </ParamField>

    <ParamField path="token.env" type="string" required={false}>
      Environment variable name containing the bearer token. When specified, the generated SDK will automatically scan for this environment variable at initialization.
    </ParamField>
  </Accordion>

  <Accordion title="OAuth client credentials">
    <Note>
      For Fern Definition, you can configure OAuth authentication either in `generators.yml` or [directly in your `api.yml` file](/api-definitions/ferndef/authentication#oauth-client-credentials). For OpenAPI, [OAuth must be configured in `generators.yml`](/api-definitions/openapi/authentication#oauth-client-credentials).
    </Note>

    Configure OAuth 2.0 client credentials authentication. Optionally configure a `refresh-token` endpoint for token renewal without re-authentication.

    ```yaml title="generators.yml" maxLines=10
    auth-schemes:
      my-oauth: # User-defined scheme name
        scheme: oauth
        type: client-credentials
        scopes:
          - "read:users"
          - "write:users"
        client-id-env: "OAUTH_CLIENT_ID" # SDK will auto-scan this environment variable
        client-secret-env: "OAUTH_CLIENT_SECRET" # SDK will auto-scan this environment variable
        token-prefix: "Bearer"
        token-header: "Authorization"
        get-token:
          endpoint: "auth.get_token"
          request-properties:
            client-id: "clientId"
            client-secret: "clientSecret"
            scopes: "scope"
          response-properties:
            access-token: "access_token"
            expires-in: "expires_in"
            refresh-token: "refresh_token"
        refresh-token:
          endpoint: "auth.refresh_token"
          request-properties:
            refresh-token: "refreshToken"
          response-properties:
            access-token: "access_token"
            expires-in: "expires_in"
            refresh-token: "refresh_token"
    ```

    <ParamField path="scheme" type="'oauth'" required={true}>
      Must be set to `"oauth"` for OAuth authentication schemes.
    </ParamField>

    <ParamField path="type" type="'client-credentials'" required={true}>
      The OAuth 2.0 grant type. Currently only `"client-credentials"` is supported.
    </ParamField>

    <ParamField path="scopes" type="list of strings" required={false}>
      OAuth scopes to request when obtaining access tokens (e.g., `"read:users"`, `"write:orders"`).
    </ParamField>

    <ParamField path="client-id-env" type="string" required={false}>
      Environment variable name containing the OAuth client ID. When specified, the generated SDK will automatically scan for this environment variable at initialization.
    </ParamField>

    <ParamField path="client-secret-env" type="string" required={false}>
      Environment variable name containing the OAuth client secret. When specified, the generated SDK will automatically scan for this environment variable at initialization.
    </ParamField>

    <ParamField path="token-prefix" type="string" default="Bearer">
      Prefix added to the access token in the Authorization header (e.g., `"Bearer"` results in `"Authorization: Bearer <token>"`). Useful when your API expects a custom format.
    </ParamField>

    <ParamField path="token-header" type="string" default="Authorization">
      HTTP header name used to send the access token. Defaults to `"Authorization"` but can be customized if your API uses a different header (e.g., `"X-API-Token"`).
    </ParamField>

    #### `get-token`

    Specifies the endpoint that exchanges client credentials for an access token. This endpoint is called automatically when the SDK client is initialized.

    ```yaml title="generators.yml"
    get-token:
      endpoint: "auth.get_token"
      request-properties:
        client-id: "clientId"
        client-secret: "clientSecret"
      response-properties:
        access-token: "access_token"
        expires-in: "expires_in"
    ```

    <ParamField path="endpoint" type="string" required={true}>
      The endpoint that issues access tokens, such as `'auth.get_token'`.
    </ParamField>

    <ParamField path="request-properties" type="object" required={false}>
      Maps OAuth parameter names to your API's request field names. Use this when your token endpoint expects different field names than the OAuth standard (e.g., your API uses `clientId` instead of `client_id`).
    </ParamField>

    <ParamField path="request-properties.client-id" type="string" required={false}>
      The request field name for the client ID in your API (e.g., `"clientId"`, `"client_id"`).
    </ParamField>

    <ParamField path="request-properties.client-secret" type="string" required={false}>
      The request field name for the client secret in your API (e.g., `"clientSecret"`, `"client_secret"`).
    </ParamField>

    <ParamField path="request-properties.scopes" type="string" required={false}>
      The request field name for scopes in your API (e.g., `"scope"`, `"scopes"`).
    </ParamField>

    <ParamField path="response-properties" type="object" required={false}>
      Maps your API's response field names to OAuth standard names. Use this when your API returns tokens with different field names (e.g., `accessToken` instead of `access_token`).
    </ParamField>

    <ParamField path="response-properties.access-token" type="string" required={false}>
      The response field name for the access token in your API (e.g., `"accessToken"`, `"access_token"`).
    </ParamField>

    <ParamField path="response-properties.expires-in" type="string" required={false}>
      The response field name for token expiration time in seconds (e.g., `"expiresIn"`, `"expires_in"`). When present, the SDK automatically refreshes tokens before expiration.
    </ParamField>

    <ParamField path="refresh-token" type="string" required={false}>
      The response field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`). Required if using the `refresh-token` flow.
    </ParamField>

    #### `refresh-token`

    Specifies the endpoint that exchanges a refresh token for a new access token. When configured, the SDK automatically uses this endpoint to renew expired tokens without re-sending credentials. If not configured, the SDK will re-authenticate using `get-token` when tokens expire.

    ```yaml title="generators.yml"
    refresh-token:
      endpoint: "auth.refresh_token"
      request-properties:
        refresh-token: "refreshToken"
      response-properties:
        access-token: "access_token"
        expires-in: "expires_in"
    ```

    <ParamField path="endpoint" type="string" required={true}>
      The endpoint that refreshes access tokens (e.g., `"POST /oauth/refresh"` or `"auth.refreshToken"`).
    </ParamField>

    <ParamField path="request-properties" type="object" required={false}>
      Maps OAuth parameter names to your API's request field names for the refresh flow.
    </ParamField>

    <ParamField path="request-properties.refresh-token" type="string" required={true}>
      The request field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`).
    </ParamField>

    <ParamField path="response-properties" type="object" required={false}>
      Maps your API's refresh response field names to OAuth standard names.
    </ParamField>

    <ParamField path="response-properties.access-token" type="string" required={false}>
      The response field name for the new access token (e.g., `"accessToken"`, `"access_token"`).
    </ParamField>

    <ParamField path="response-properties.expires-in" type="string" required={false}>
      The response field name for the new token's expiration time in seconds (e.g., `"expiresIn"`, `"expires_in"`).
    </ParamField>

    <ParamField path="response-properties.refresh-token" type="string" required={false}>
      The response field name if your API issues a new refresh token with each refresh (token rotation).
    </ParamField>
  </Accordion>
</AccordionGroup>

## `api`

Defines the API specification (OpenAPI, AsyncAPI, etc.) and how to parse it. For Fern Definition, no API reference is needed – [Fern automatically detects your spec](/sdks/overview/project-structure#generatorsyml).

```yaml title="generators.yml" maxLines=10
api:
  settings:
    inline-path-parameters: true # Applies to all OpenAPI specs
  specs:
    - openapi: "./openapi.yml"
      namespace: "v1"
      settings:
        title-as-schema-name: true # Applies only to this OpenAPI spec
    - asyncapi: "./events.yml"
      namespace: "events"
  headers:
    Authorization: "Bearer ${API_TOKEN}"
  environments:
    production: "https://api.prod.com"
    staging: "https://api.staging.com"
```

<ParamField path="auth" type="object" toc={true}>
  Authentication configuration for the API.
</ParamField>

<ParamField path="headers" type="string or list of objects" toc={true}>
  Global headers to include with all API requests. You can specify headers as simple string values or as objects with additional configuration for code generation.

  <AccordionGroup>
    <Accordion title="Simple string values">
      ```yaml title="generators.yml"
      api:
        headers:
          Authorization: "Bearer ${API_TOKEN}"
          X-App-Version: "1.0.0"
      ```
    </Accordion>

    <Accordion title="Advanced configuration with type information">
      ```yaml title="generators.yml"
      api:
        - openapi: ./path/to/openapi
          headers: 
            X-Version: 
              # The variable name to use in generated SDK code. 
              # If not specified, uses the header name.
              name: version 
              # The type of the header value for code generation 
              # (e.g., "string", "literal<'value'>", "number").
              type: literal<"1234">
      ```
    </Accordion>
  </AccordionGroup>
</ParamField>

<ParamField path="environments" type="object" toc={true}>
  Environment configurations for different deployment targets.
</ParamField>

<ParamField path="settings" type="object" toc={true}>
  Settings that apply to all specs of a given type (e.g., all OpenAPI specs). Can be overridden at the spec or generator level. Precedence: generator-level settings override spec-level settings, which override global settings.

  For example, use this to ensure consistent parsing behavior across all your OpenAPI specs. For available settings, see the [specification type](#specification-types) documentation below.
</ParamField>

### Specification types

Each specification type (OpenAPI, AsyncAPI, etc.) supports various configuration options including the spec file location, namespace, overrides, and type-specific settings.

<AccordionGroup>
  <Accordion title="OpenAPI">
    ```yaml title="generators.yml"
    api:
      specs:
        - openapi: "./openapi.yml"
          origin: "https://api.example.com/openapi.json"
          overlays: "./openapi-overlays.yml"
          overrides: "./openapi-overrides.yml"
          namespace: "v1"
          settings:
            title-as-schema-name: true
            inline-path-parameters: false
            inline-all-of-schemas: true
            prefer-undiscriminated-unions-with-literals: true
            filter:
              endpoints: ["POST /users", "GET /users/{id}"]
            example-generation:
              request:
                max-depth: 2
    ```

    <ParamField path="openapi" type="string" required={true} toc={true}>
      Path to the OpenAPI specification file.
    </ParamField>

    <ParamField path="origin" type="string" toc={true}>
      URL of the API definition origin for pulling updates. For instructions on how to set up automatic syncing, refer to [Sync your OpenAPI specification](/learn/api-definitions/openapi/sync-your-open-api-specification).
    </ParamField>

    <ParamField path="overlays" type="string" toc={true}>
      Path to an [OpenAPI Overlay](/learn/api-definitions/openapi/overlays) file. Overlays follow the [OpenAPI Overlay Specification](https://spec.openapis.org/overlay/v1.0.0.html) and are the recommended approach for customizing OpenAPI specifications.
    </ParamField>

    <ParamField path="overrides" type="string" toc={true}>
      Path to OpenAPI overrides file. Consider using `overlays` instead for a standards-based approach.
    </ParamField>

    <ParamField path="namespace" type="string" toc={true}>
      Namespace for the specification. Useful for configuring a [single package with multiple API versions](/api-definitions/overview/project-structure#option-2-namespace-based-versioning).
    </ParamField>

    <ParamField path="settings" type="object" toc={true}>
      OpenAPI-specific generation settings for this individual spec. To apply the same settings across all OpenAPI specs, use global [`api.settings`](/learn/sdks/reference/generators-yml#settings) instead.
    </ParamField>

    <ParamField path="settings.title-as-schema-name" type="boolean" default="false" toc={true}>
      Whether to use the titles of schemas within an OpenAPI definition as the names of types within Fern.
    </ParamField>

    <ParamField path="settings.inline-path-parameters" type="boolean" default="true" toc={true}>
      Whether to include path parameters within the generated in-lined request.
    </ParamField>

    <ParamField path="settings.inline-all-of-schemas" type="boolean" default="false" toc={true}>
      Whether to inline `allOf` schemas during code generation. When true, Fern recursively visits `allOf` schema definitions and inlines them into the child schema. When false, `allOf` schemas are extended through inheritance.

      Enabling this setting allows child schemas to override parent property requirements. For example, a child schema can mark a parent's required property as optional. Without this setting, Fern ignores the child schema's optional declaration and preserves the parent schema's requirement instead.
    </ParamField>

    <ParamField path="settings.prefer-undiscriminated-unions-with-literals" type="boolean" default="false" toc={true}>
      Whether to prefer undiscriminated unions with literals.
    </ParamField>

    <ParamField path="settings.only-include-referenced-schemas" type="boolean" default="false" toc={true}>
      Whether to only include schemas referenced by endpoints in the generated SDK (tree-shaking).
    </ParamField>

    <ParamField path="settings.respect-nullable-schemas" type="boolean" default="true" toc={true}>
      Preserves nullable schemas in API definition settings. When false, nullable schemas are treated as optional.
    </ParamField>

    <ParamField path="settings.object-query-parameters" type="boolean" default="true" toc={true}>
      Enables parsing deep object query parameters.
    </ParamField>

    <ParamField path="settings.wrap-references-to-nullable-in-optional" type="boolean" default="false" toc={true}>
      Controls whether references to nullable schemas are wrapped in optional types. When false, nullable references are treated as required fields that can be null.
    </ParamField>

    <ParamField path="settings.coerce-optional-schemas-to-nullable" type="boolean" default="false" toc={true}>
      Controls whether optional schemas are coerced to nullable types during code generation. When false, optional and nullable are treated as distinct concepts.
    </ParamField>

    <ParamField path="settings.respect-readonly-schemas" type="boolean" toc={true}>
      Enables exploring readonly schemas in OpenAPI specifications.
    </ParamField>

    <ParamField path="settings.respect-forward-compatible-enums" type="boolean" default="false" toc={true}>
      Enables respecting forward compatible enums in OpenAPI specifications.
    </ParamField>

    <ParamField path="settings.use-bytes-for-binary-response" type="boolean" toc={true}>
      Enables using the `bytes` type for binary responses. Defaults to file stream.
    </ParamField>

    <ParamField path="settings.default-form-parameter-encoding" type="string" default="json" toc={true}>
      The default encoding of form parameters. Options: `form`, `json`.
    </ParamField>

    <ParamField path="settings.additional-properties-defaults-to" type="boolean" default="false" toc={true}>
      Configure what `additionalProperties` should default to when not explicitly defined on a schema.
    </ParamField>

    <ParamField path="settings.type-dates-as-strings" type="boolean" default="false" toc={true}>
      If true, convert strings with format date to strings. If false, convert to dates.
    </ParamField>

    <ParamField path="settings.preserve-single-schema-oneof" type="boolean" default="false" toc={true}>
      If true, preserve oneOf structures with a single schema. If false, unwrap them.
    </ParamField>

    <ParamField path="settings.filter.endpoints" type="list of strings" toc={true}>
      Endpoints to include in the generated SDK (e.g., "POST /users").
    </ParamField>

    <ParamField path="settings.example-generation.request.max-depth" type="integer" toc={true}>
      Controls the maximum depth for which optional properties will have examples generated. A depth of 0 means no optional properties will have examples.
    </ParamField>

    <ParamField path="settings.example-generation.response.max-depth" type="integer" toc={true}>
      Controls the maximum depth for which optional properties will have examples generated in responses.
    </ParamField>

    <ParamField path="settings.coerce-enums-to-literals" type="boolean" default="false" toc={true}>
      Controls whether enums are converted to literal types during code generation. When `false` (default), enums are preserved as enum types, maintaining the original enum structure from your OpenAPI specification. When `true`, enums are coerced to literal types, which can be useful for simpler type representations in generated code.
    </ParamField>

    <ParamField path="settings.idiomatic-request-names" type="boolean" default="true" toc={true}>
      Controls the naming convention for autogenerated request names. When enabled, places the verb before the noun in request names (e.g., `UsersListRequest` becomes `ListUsersRequest`), following more idiomatic naming patterns.
    </ParamField>

    <ParamField path="settings.resolve-aliases" type="boolean" default="false" toc={true}>
      Inlines type aliases to simplify your generated SDK. When enabled, reduces
      unnecessary type definitions by replacing simple aliases with their underlying
      types directly. Useful for OpenAPI specs with many primitive or simple type
      aliases.

      Set to `true` to inline all aliases, or use an object with an `except` array
      to preserve specific type aliases:

      ```yaml
      settings:
        # Inline all aliases
        resolve-aliases: true

        # Or preserve specific aliases
        resolve-aliases:
          except:
            - UserId
            - OrganizationId
      ```
    </ParamField>

    <ParamField path="settings.group-environments-by-host" type="boolean" default="false" toc={true}>
      When enabled, groups servers by host into unified environments, enabling APIs with multiple protocols (REST, WebSocket, etc.) to share environment configuration. Environment URL IDs use the server name, with path or protocol suffixes added only when needed to resolve collisions.
    </ParamField>
  </Accordion>

  <Accordion title="AsyncAPI">
    ```yaml
    api:
      specs:
        - asyncapi: "./asyncapi.yml"
          origin: "https://api.example.com/asyncapi.json"
          overrides: "./asyncapi-overrides.yml"
          namespace: "events"
          settings:
            message-naming: "v2"
            title-as-schema-name: false
            respect-nullable-schemas: true
    ```

    <ParamField path="asyncapi" type="string" required={true} toc={true}>
      Path to the AsyncAPI specification file.
    </ParamField>

    <ParamField path="origin" type="string" toc={true}>
      URL of the API definition origin for pulling updates.
    </ParamField>

    <ParamField path="overrides" type="string" toc={true}>
      Path to AsyncAPI overrides file.
    </ParamField>

    <ParamField path="namespace" type="string" toc={true}>
      Namespace for the specification. Useful for configuring a [single package with multiple API versions](/api-definitions/overview/project-structure#option-2-namespace-based-versioning).
    </ParamField>

    <ParamField path="settings" type="object" toc={true}>
      AsyncAPI-specific generation settings for this individual spec. To apply the same settings across all AsyncAPI specs, use global [`api.settings`](/learn/sdks/reference/generators-yml#settings) instead.
    </ParamField>

    <ParamField path="settings.message-naming" type="object" default="v1" toc={true}>
      What version of message naming to use for AsyncAPI messages. Options: `v1`, `v2`.
    </ParamField>

    <ParamField path="settings.title-as-schema-name" type="boolean" default="false" toc={true}>
      Whether to use the titles of schemas within an AsyncAPI definition as the names of types within Fern.
    </ParamField>

    <ParamField path="settings.respect-nullable-schemas" type="boolean" default="true" toc={true}>
      Preserves nullable schemas in API definition settings. When false, nullable schemas are treated as optional.
    </ParamField>

    <ParamField path="settings.idiomatic-request-names" type="boolean" default="true" toc={true}>
      Controls the naming convention for autogenerated request names. When enabled, places the verb before the noun in request names (e.g., `UsersListRequest` becomes `ListUsersRequest`), following more idiomatic naming patterns.
    </ParamField>

    <ParamField path="settings.wrap-references-to-nullable-in-optional" type="boolean" default="false" toc={true}>
      Controls whether references to nullable schemas are wrapped in optional types. When false, nullable references are treated as required fields that can be null.
    </ParamField>

    <ParamField path="settings.coerce-optional-schemas-to-nullable" type="boolean" default="false" toc={true}>
      Controls whether optional schemas are coerced to nullable types during code generation. When false, optional and nullable are treated as distinct concepts.
    </ParamField>

    <ParamField path="settings.group-environments-by-host" type="boolean" default="false" toc={true}>
      When enabled, groups servers by host into unified environments, enabling APIs with multiple protocols (REST, WebSocket, etc.) to share environment configuration. Environment URL IDs use the server name, with path or protocol suffixes added only when needed to resolve collisions.
    </ParamField>
  </Accordion>

  <Accordion title="gRPC/proto buffers">
    ```yaml title="generators.yml"
    api:
      specs:
        - proto:
            root: "./proto"
            target: "proto/service/v1/service.proto"
            local-generation: true
    ```

    <ParamField path="root" type="string" required={true} toc={true}>
      Path to the `.proto` directory root (e.g., `proto`). Must be specified up to where the package starts. For example, if your package is `package.test.v1` at the file path `protos/package/test/v1/test_file.proto`, the root should be `protos/`
    </ParamField>

    <ParamField path="target" type="string" toc={true} required={false}>
      Path to the target `.proto` file (e.g., `proto/user/v1/user.proto`). Omit to generate docs for the entire root folder.
    </ParamField>

    <ParamField path="overrides" type="string" toc={true}>
      Path to the overrides configuration file. Used for SDK generation only, not for documentation generation.
    </ParamField>

    <ParamField path="local-generation" type="boolean" default="false" toc={true}>
      Whether to compile `.proto` files locally. Defaults to remote generation (`false`). When enabled, you must have [buf](https://buf.build/docs/installation) installed on your machine or in your [CI/CD environment (e.g., GitHub Actions)](/learn/api-definitions/grpc/sync-your-g-rpc-specification).
    </ParamField>
  </Accordion>

  <Accordion title="OpenRPC">
    <ParamField path=".openrpc" type="string" required={true} toc={true}>
      Path to the OpenRPC specification file.
    </ParamField>

    <ParamField path="overrides" type="string" toc={true}>
      Path to OpenRPC overrides file.
    </ParamField>

    <ParamField path="namespace" type="string" toc={true}>
      Namespace for the specification.
    </ParamField>
  </Accordion>

  <Accordion title="Conjure">
    ```yaml title="generators.yml"
    api:
      specs:
        conjure: "./conjure-api.yml"
    ```

    <ParamField path="conjure" type="string" toc={true}>
      Path to Conjure specification file.
    </ParamField>
  </Accordion>
</AccordionGroup>

## `whitelabel`

Configuration for publishing generated SDKs without Fern branding. When enabled, removes all mentions of Fern from the generated code and allows publishing under your own brand.

```yaml title="generators.yml"
whitelabel:
  github:
    username: "company-github-username"
    email: "my-email@example.com"
    token: "ghp_xxxxxxxxxxxx"
```

<ParamField path="username" type="string" required={true} toc={true}>
  The GitHub username that will be used for committing and publishing the whitelabeled SDK code to GitHub repositories. This should be the username of the account that has write access to your target repositories.
</ParamField>

<ParamField path="email" type="string" required={true} toc={true}>
  The email address associated with the GitHub account. This email will be used in Git commits when publishing the whitelabeled SDK code and should match the email configured in your GitHub account settings.
</ParamField>

<ParamField path="token" type="string" required={true} toc={true}>
  A GitHub Personal Access Token (PAT) with appropriate permissions for repository access. The token should have `repo` scope permissions to allow reading from and writing to your repositories for publishing whitelabeled SDKs.
</ParamField>

## `metadata`

Package metadata like description and authors that gets included in all generated SDKs. Alternatively, you can [define metadata for individual SDKs](#metadata-2).

```yaml title="generators.yml"
metadata:
  description: "My API SDK"
  authors:
    - name: "John Doe"
      email: "john@example.com"
    - name: "Jane Smith"
      email: "jane@example.com"
```

<ParamField path="description" type="string" required={false} toc={true}>
  A brief description of the SDK that will be included in package metadata. This description helps users understand what your SDK does when they discover it in package repositories.
</ParamField>

### `authors`

A list of authors who will be credited in the generated SDK's package metadata.

<ParamField path="name" type="string" required={true} toc={true}>
  The full name of the author to be credited in the SDK package metadata.
</ParamField>

<ParamField path="email" type="string" required={true} toc={true}>
  The email address of the author. This will be included in package metadata and may be used by package managers for contact information.
</ParamField>

## `readme`

Controls what goes into the generated README files across all SDKs, allowing you to customize the content and structure of your SDK documentation.

```yaml title="generators.yml" maxLines=10
readme:
  bannerLink: "https://example.com/banner"
  introduction: "Welcome to our API"
  apiReferenceLink: "https://docs.example.com"
  apiName: "Example Product"
  exampleStyle: "minimal"
  disabledSections:
    - "contributing"
  defaultEndpoint:
    method: "POST"
    path: "/users"
    stream: false
  customSections:
    - title: "Custom Section"
      language: "java"
      content: |
        This is a custom section. Latest package info is {{ group }}:{{ artifact }}:{{ version }}.
    - title: "Custom Section"
      language: "typescript"
      content: |
        Custom section for {{ packageName }}
    - title: "Another Custom Section"
      language: "typescript"
      content: |
        A second custom section for {{ packageName }}
  features:
    authentication:
      - method: "POST"
        path: "/auth/login"
      - "GET /auth/profile"
    users:
      - method: "GET"
        path: "/users"
      - method: "POST"
        path: "/users"
```

<ParamField path="bannerLink" type="string" required={false} toc={true}>
  URL for a banner image or link that appears at the top of the README.
</ParamField>

<ParamField path="introduction" type="string" required={false} toc={true}>
  Custom introduction text that appears at the beginning of the README.
</ParamField>

<ParamField path="apiReferenceLink" type="string" required={false} toc={true}>
  URL to your external API documentation or reference guide.
</ParamField>

<ParamField path="apiName" type="string" required={false} toc={true}>
  Name of the API that appears in the README. Will appear as `Your Api Name SDK` or `Your Api Name API` throughout the README. Defaults to organization name if not set.
</ParamField>

<ParamField path="exampleStyle" type="'minimal' | 'comprehensive'" required={false} default="comprehensive" toc={true}>
  Controls whether usage examples show only required parameters (`minimal`) or all parameters (`comprehensive`). Currently only supported for Java SDKs.
</ParamField>

<ParamField path="disabledSections" type="list of strings" required={false} toc={true}>
  Sections to disable in the README. Supported values: `"contributing"`.
</ParamField>

<ParamField path="features" type="list of objects" required={false} toc={true}>
  Organizes endpoints into named feature sections within the README. Each feature creates a dedicated section with example code snippets for the specified endpoints.
</ParamField>

<AccordionGroup>
  <Accordion title="Endpoint configuration">
    Specifies which endpoint's code snippet to showcase as the primary example in the README.

    <ParamField path="defaultEndpoint.method" type="string" required={true} toc={true}>
      HTTP method of the default endpoint (e.g., `GET`, `POST`, `PUT`, `DELETE`).
    </ParamField>

    <ParamField path="defaultEndpoint.path" type="string" required={true} toc={true}>
      Endpoint path for the default example (e.g., `/users`, `/auth/login`).
    </ParamField>

    <ParamField path="defaultEndpoint.stream" type="boolean" required={false} default="false" toc={true}>
      Whether the endpoint is a streaming endpoint. Defaults to `false`.
    </ParamField>
  </Accordion>

  <Accordion title="Custom sections">
    Define a custom section in the generated README for a specific SDK.

    <ParamField path="customSections.title" type="string" required={true} toc={true}>
      The title of the custom section as it will appear in the README.
    </ParamField>

    <ParamField path="customSections.language" type="'java' | 'typescript'" required={true} toc={true}>
      The target SDK language for this section. The custom section will only appear in README files generated for the specified language.
    </ParamField>

    <ParamField path="customSections.content" type="string" required={true} toc={true}>
      The Markdown content of the custom section. You can use template variables in the format `{{ variable }}` that will be dynamically replaced with values specific to each SDK language when the README is generated.

      Available template variables by language:

      | Language   | Variable      | Description                                                                                                                                                                |
      | ---------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
      | TypeScript | `packageName` | Name of your package, as specified in the [`package-name` field](/sdks/generators/typescript/configuration#package-name)                                                   |
      | Python     | `packageName` | Name of your package, as specified in the [`package_name` field](/sdks/generators/python/configuration#package_name)                                                       |
      | Go         | `owner`       | The owner of your Go module                                                                                                                                                |
      | Go         | `repo`        | The [repository](/sdks/generators/go/publishing#configure-output-location) where your Go module is published                                                               |
      | Go         | `version`     | SDK version                                                                                                                                                                |
      | Java       | `group`       | Maven `groupId` [from `coordinate` field](/sdks/generators/java/publishing#configure-maven-coordinate)                                                                     |
      | Java       | `artifact`    | Maven `artifactId` [from `coordinate` field](/sdks/generators/java/publishing#configure-maven-coordinate)                                                                  |
      | Java       | `version`     | SDK version                                                                                                                                                                |
      | C#/.NET    | `packageName` | Name of your package, as specified in the [`package-name` field](/sdks/generators/csharp/configuration#package-name)                                                       |
      | PHP        | `packageName` | Name of your package, as specified in the [`package-name` field](/sdks/generators/php/configuration#package-name)                                                          |
      | Ruby       | `packageName` | Name of your package, as specified in the [`package-name` field](/sdks/generators/ruby/configuration#package-name)                                                         |
      | Swift      | `gitUrl`      | The [URL](/sdks/generators/swift/publishing#verify-package-availability) where your Swift package is published. For example, `https://github.com/fern-api/basic-swift-sdk` |
      | Swift      | `minVersion`  | SDK version                                                                                                                                                                |
    </ParamField>
  </Accordion>
</AccordionGroup>

## `default-group`

Which generator group to use when none is specified.

```yaml
default-group: "production"
```

<ParamField path="default-group" type="string" required={false} toc={true} />

## `autorelease`

Enable or disable [Fern Autorelease](/learn/sdks/overview/autorelease) globally for automated SDK releases. Alternatively, you can [configure autorelease for individual SDKs](#autorelease-2).

```yaml title="generators.yml"
autorelease: true
```

<ParamField path="autorelease" type="boolean | object" default={false} required={false} toc={true}>
  Set to `true` to enable Autorelease, `false` to disable it. Explicit configuration in `generators.yml` takes precedence over other enablement methods. [Per-generator settings](#autorelease-2) override this global configuration.
</ParamField>

<Accordion title="Enable with pull-based detection">
  Configure a cron schedule to periodically fetch and check for spec changes:

  ```yaml title="generators.yml"
  autorelease:
    cron:
      schedule: "0 0 * * 0"  # Weekly on Sunday at midnight
  ```

  <ParamField path="cron.schedule" type="string" required={true} toc={true}>
    A cron expression defining how often to check for spec changes. Uses standard cron syntax.
  </ParamField>
</Accordion>

## `aliases`

Define shortcuts that map to multiple generator groups, allowing you to run several groups with a single command. When you run `fern generate --group <alias>`, all groups in the alias run in parallel. You can also set an alias as your `default-group`.

```yaml title="generators.yml" {1-4}
aliases:
  all: ["php-sdk", "ts-sdk", "go-sdk"]
  frontend: ["ts-sdk"]
  backend: ["php-sdk", "go-sdk"]

groups:
  php-sdk:
    generators:
      - name: fernapi/fern-php-sdk
        version: 1.0.0
  ts-sdk:
    generators:
      - name: fernapi/fern-typescript-sdk
        version: 1.0.0
  go-sdk:
    generators:
      - name: fernapi/fern-go-sdk
        version: 1.0.0
```

<ParamField path="aliases" type="map<string, list<string>>" required={false} toc={true}>
  A map where each key is an alias name and the value is a list of group names. Each group name must reference a group defined in the `groups` section.
</ParamField>

## `groups`

Organizes user-defined sets of generators, typically grouped by environment (like "production", "staging") or language (like "typescript", "python"). You can also create [aliases](#aliases) to run multiple groups with a single command.

```yaml title="generators.yml" maxLines=10
groups:
  typescript-sdk: # User-defined name
    audiences: ["external"]
    generators:
      - name: fernapi/fern-typescript-sdk
        version: 0.9.0
        output:
          location: npm
          package-name: "@myorg/api-sdk"
          token: "${NPM_TOKEN}"
        github:
          repository: your-organization/company-typescript
          mode: "pull-request"
    metadata:
      description: "TypeScript SDK for MyAPI"
      authors:
        - name: "SDK Team"
          email: "sdk@myorg.com"
    reviewers:
      teams:
        - name: "sdk-team"
```

<ParamField path="audiences" type="list of strings" required={false}>
  Target audiences for this generator group (e.g., "external", "internal")
</ParamField>

### `reviewers`

Set code reviewers for an individual SDK. Alternatively, you can [configure reviewers globally for all SDKs](#reviewers-4).

```yaml title="generators.yml"
reviewers:
  teams:
    - name: "sdk-team"
    - name: "api-team"
  users:
    - name: "john-doe"
    - name: "jane-smith"
```

<ParamField path="teams" type="list of strings" required={false} toc={true}>
  GitHub team names that should review generated code.
</ParamField>

<ParamField path="users" type="list of strings" required={false} toc={true}>
  GitHub users that should review generated code.
</ParamField>

<ParamField path="teams.name" type="string" required={true} toc={true}>
  Name of a GitHub team.
</ParamField>

<ParamField path="users.name" type="string" required={true} toc={true}>
  Name of a GitHub user.
</ParamField>

### `generators`

Generator settings for a specific group.

```yaml title="generators.yml"
groups:
  typescript-sdk: # User-defined name
    audiences: ["external"]
    generators:
      - name: fernapi/fern-typescript-sdk
        version: 0.9.0
        smart-casing: true
```

<ParamField path="name" type="string" required={true}>
  The Fern generator package name (e.g., fernapi/fern-typescript-sdk)
</ParamField>

<ParamField path="version" type="string" required={true}>
  Specific version of the generator to use
</ParamField>

<ParamField path="smart-casing" type="boolean" default="false">
  Enables intelligent case conversion that preserves numbers and common programming patterns:

  * Numbers stay intact (e.g., `v2` instead of `v_2`, `getUsersV2` instead of `getUsersV_2`)
  * Initialisms are preserved (e.g., `CustomerID` instead of `CustomerId`)
  * Acronyms remain correct (e.g., `HTTPSConnection` stays `HTTPSConnection`)
</ParamField>

#### `config`

Language-specific configuration options.

```yaml title="generators.yml"
groups:
  ts-sdk: # Typescript SDK group
    generators:
      - name: fernapi/fern-typescript-sdk
        version: 3.46.3
        config: # TypeScript-specific config options
          namespaceExport: AcmePayments
          noSerdeLayer: false
```

<CardGroup cols={3}>
  <Card title="TypeScript" href="/sdks/generators/typescript/configuration" />

  <Card title="Python" href="/sdks/generators/python/configuration" />

  <Card title="Go" href="/sdks/generators/go/configuration" />

  <Card title="Java" href="/sdks/generators/java/configuration" />

  <Card title=".NET" href="/sdks/generators/csharp/configuration" />

  <Card title="PHP" href="/sdks/generators/php/configuration" />

  <Card title="Ruby" href="/sdks/generators/ruby/configuration" />

  <Card title="Swift" href="/sdks/generators/swift/configuration" />
</CardGroup>

#### `output`

Where to publish the generated SDK.

```yaml title="generators.yml"
groups:
  typescript-sdk: # User-defined name
    audiences: ["external"]
    generators:
      - name: fernapi/fern-typescript-sdk
        version: 0.9.0
        output:
          location: npm
          package-name: "@myorg/api-sdk"
          token: "${NPM_TOKEN}"
```

<AccordionGroup>
  <Accordion title="npm">
    Publish TypeScript SDKs to the npm registry.

    ```yaml title="generators.yml"
    output:
      location: npm
      package-name: "@myorg/api-sdk"
      token: "${NPM_TOKEN}"
    ```

    <ParamField path="location" type="'npm'" required={true}>
      Set to "npm" for NPM publishing
    </ParamField>

    <ParamField path="url" type="string" required={false} default="npmjs.com">
      Custom NPM registry URL
    </ParamField>

    <ParamField path="package-name" type="string" required={true}>
      NPM package name (e.g., "@myorg/api-sdk")
    </ParamField>

    <ParamField path="token" type="string" required={false}>
      NPM authentication token for publishing
    </ParamField>
  </Accordion>

  <Accordion title="Maven">
    Publish Java SDKs to Maven repository.

    ```yaml title="generators.yml"
    output:
      location: maven
      coordinate: "com.myorg:api-sdk"
      username: "${MAVEN_USERNAME}"
      password: "${MAVEN_PASSWORD}"
      signature:
        keyId: "ABC123"
        password: "${GPG_PASSWORD}"
        secretKey: "${GPG_SECRET_KEY}"
    ```

    <ParamField path="location" type="'maven'" required={true}>
      Set to "maven" for Maven publishing
    </ParamField>

    <ParamField path="url" type="string" required={false} default="npmjs.com">
      Maven repository URL (optional, defaults to Maven Central)
    </ParamField>

    <ParamField path="coordinate" type="string" required={true}>
      Maven artifact coordinate in "groupId:artifactId" format
    </ParamField>

    <ParamField path="username" type="string" required={false}>
      Repository authentication username
    </ParamField>

    <ParamField path="password" type="string" required={false}>
      Repository authentication password
    </ParamField>

    <ParamField path="signature" type="object" required={false}>
      GPG signature configuration for package signing
    </ParamField>

    <ParamField path="signature.keyId" type="string" required={true}>
      GPG key ID for package signing
    </ParamField>

    <ParamField path="signature.password" type="string" required={true}>
      GPG key password
    </ParamField>

    <ParamField path="signature.secretKey" type="string" required={true}>
      GPG secret key content
    </ParamField>
  </Accordion>

  <Accordion title="PyPI">
    Publish Python SDKs to Python Package Index.

    ```yaml title="generators.yml"
    output:
      location: pypi
      package-name: "myorg-api-sdk"
      token: "${PYPI_TOKEN}"
      metadata:
        keywords: ["api", "sdk", "client"]
        documentation-link: "https://docs.myorg.com"
        homepage-link: "https://myorg.com"
    ```

    <ParamField path="location" type="'pypi'" required={true}>
      Set to "pypi" for PyPI publishing
    </ParamField>

    <ParamField path="url" type="string" required={false}>
      Custom PyPI registry URL (optional, defaults to PyPI)
    </ParamField>

    <ParamField path="package-name" type="string" required={true}>
      Python package name (e.g., "myorg-api-sdk")
    </ParamField>

    <ParamField path="token" type="string" required={false}>
      PyPI authentication token for publishing
    </ParamField>

    <ParamField path="username" type="string" required={false}>
      PyPI username (alternative to token authentication)
    </ParamField>

    <ParamField path="password" type="string" required={false}>
      PyPI password (alternative to token authentication)
    </ParamField>

    <ParamField path="metadata" type="objecta" required={false}>
      Additional PyPI-specific metadata for the package
    </ParamField>

    <ParamField path="metadata.keywords" type="list of string" required={false}>
      Package keywords for PyPI search and discovery
    </ParamField>

    <ParamField path="metadata.documentation-link" type="string" required={false}>
      Link to package documentation
    </ParamField>

    <ParamField path="metadata.homepage-link" type="string" required={false}>
      Link to project homepage
    </ParamField>
  </Accordion>

  <Accordion title="NuGet">
    Publish .NET SDKs to NuGet repository.

    ```yaml title="generators.yml"
    output:
      location: nuget
      package-name: "MyOrg.ApiSdk"
      api-key: "${NUGET_API_KEY}"
    ```

    <ParamField path="location" type="'nuget'" required={true}>
      Set to "nuget" for NuGet publishing
    </ParamField>

    <ParamField path="url" type="string" required={false}>
      Custom NuGet feed URL (optional, defaults to nuget.org)
    </ParamField>

    <ParamField path="package-name" type="string" required={true}>
      NuGet package name (e.g., "MyOrg.ApiSdk")
    </ParamField>

    <ParamField path="api-key" type="string" required={false}>
      NuGet API key for publishing to the feed
    </ParamField>
  </Accordion>

  <Accordion title="RubyGems">
    Publish Ruby SDKs to RubyGems registry.

    ```yaml title="generators.yml"
    output:
      location: rubygems
      package-name: "myorg_api_sdk"
      api-key: "${RUBYGEMS_API_KEY}"
    ```

    <ParamField path="location" type="'rubygems'" required={true}>
      Set to "rubygems" for RubyGems publishing
    </ParamField>

    <ParamField path="url" type="string" required={false}>
      Custom RubyGems registry URL (optional, defaults to rubygems.org)
    </ParamField>

    <ParamField path="package-name" type="string" required={true}>
      Ruby gem package name (e.g., "myorg\_api\_sdk")
    </ParamField>

    <ParamField path="api-key" type="string" required={false}>
      RubyGems API key for publishing (requires "Push rubygem" permission)
    </ParamField>

    > **Note**: RubyGems API keys need "Push rubygem" permission and ideally "index" and "yank rubygem" permissions. If MFA is enabled, ensure MFA settings don't require MFA for API key usage.
  </Accordion>

  <Accordion title="Postman">
    Publish API collections to Postman workspace.

    ```yaml title="generators.yml"
    output:
      location: postman
      api-key: "${POSTMAN_API_KEY}"
      workspace-id: "12345678-1234-1234-1234-123456789abc"
      collection-id: "87654321-4321-4321-4321-cba987654321"
    ```

    <ParamField path="location" type="'postman'" required={true}>
      Set to "postman" for Postman publishing
    </ParamField>

    <ParamField path="api-key" type="string" required={true}>
      Postman API key for workspace access
    </ParamField>

    <ParamField path="workspace-id" type="string" required={true}>
      Target Postman workspace ID where collection will be published
    </ParamField>

    <ParamField path="collection-id" type="string" required={false}>
      Existing collection ID to update (creates new collection if not specified)
    </ParamField>
  </Accordion>

  <Accordion title="Local file system">
    Save generated SDKs to local file system instead of publishing.

    ```yaml title="generators.yml"
    output:
      location: local-file-system
      path: "./generated-sdks/typescript"
    ```

    <ParamField path="location" type="'local-file-system'" required={true}>
      Set to "local-file-system" for local output
    </ParamField>

    <ParamField path="path" type="string" required={true}>
      Local directory path where generated files will be saved
    </ParamField>
  </Accordion>
</AccordionGroup>

#### `github`

Specify how your SDKs are generated in GitHub using the `github` configuration.
Designate the `mode` to specify how Fern handles your code changes. For cloud generation, specify the GitHub repository using `repository`. For [self-hosted generation](/learn/sdks/deep-dives/self-hosted), use `uri` and `token` instead.

<Note>
  Make sure the 

  [Fern GitHub app](https://github.com/apps/fern-api)

   is installed on your destination repository (not required for self-hosted generation)
</Note>

<AccordionGroup>
  <Accordion title="Release (recommended)">
    Fern generates your code, commits it to main, and tags a new release.

    ```yml {6-17}
    groups: 
      ts-sdk:
        generators:
          - name: fernapi/fern-typescript-sdk
          ...
            github: 
              repository: "your-org/your-repo-name"
              mode: "release"
    ```

    <ParamField path="repository" type="string" required={true} toc={true}>
      Name of your repository in GitHub.
    </ParamField>

    <ParamField path="mode" type="'release'" required={false} toc={true} />

    <ParamField path="branch" type="string" required={false} toc={true}>
      Name of your branch in GitHub.
    </ParamField>

    <ParamField path="license" type="'MIT' | 'Apache-2.0' | 'Custom License Name'" required={false} toc={true}>
      Software license for the generated SDK.
    </ParamField>

    <ParamField path="reviewers" type="{ teams: list<string>, users: list<string> }" required={false} toc={true}>
      Specify which teams and users should review generated code. See [reviewers configuration](#reviewers-1).
    </ParamField>
  </Accordion>

  <Accordion title="Pull request">
    Fern generates your code, commits to a new branch, and opens a PR for review. To publish, you must merge the PR and tag a GitHub release.

    ```yml {6-8}
    groups: 
      ts-sdk:
        generators:
          - name: fernapi/fern-typescript-sdk
          ...
            github: 
              repository: "your-org/your-repo-name"
              mode: "pull-request"
    ```

    <ParamField path="repository" type="string" required={true} toc={true}>
      Name of your repository in GitHub.
    </ParamField>

    <ParamField path="mode" type="'pull-request'" required={false} toc={true} />

    <ParamField path="branch" type="string" required={false} toc={true}>
      Name of your branch in GitHub.
    </ParamField>

    <ParamField path="license" type="'MIT' | 'Apache-2.0' | 'Custom License Name'" required={false} toc={true}>
      Software license for the generated SDK.
    </ParamField>

    <ParamField path="reviewers" type="list of objects" required={false} toc={true}>
      Specify which teams and users should review generated code. See [reviewers configuration](#reviewers-1).
    </ParamField>
  </Accordion>

  <Accordion title="Push">
    Fern generates your code and pushes it to the branch you specify.

    ```yml {6-8}
    groups: 
      ts-sdk:
        generators:
          - name: fernapi/fern-typescript-sdk
          ...
            github: 
              repository: "your-org/your-repo-name"
              mode: "push"
              branch: "your-branch-name" # required for `mode: push`
    ```

    <ParamField path="repository" type="string" required={true} toc={true}>
      Name of your repository in GitHub.
    </ParamField>

    <ParamField path="mode" type="'push'" required={false} toc={true} />

    <ParamField path="branch" type="string" required={true} toc={true}>
      Name of your branch in GitHub.
    </ParamField>

    <ParamField path="license" type="'MIT' | 'Apache-2.0' | 'Custom License Name'" required={false} toc={true}>
      Software license for the generated SDK.
    </ParamField>

    <ParamField path="reviewers" type="{ teams: list<string>, users: list<string> }" required={false} toc={true}>
      Specify which teams and users should review generated code. See [reviewers configuration](#reviewers-1).
    </ParamField>
  </Accordion>

  <Accordion title="Self-hosted">
    For [self-hosted SDK generation](/learn/sdks/deep-dives/self-hosted), configure the `github` property with `uri` and `token` instead of `repository`.

    ```yml {6-10}
    groups: 
      ts-sdk:
        generators:
          - name: fernapi/fern-typescript-sdk
          ...
            github: 
              uri: "https://github.com/your-org/your-repo-name"
              token: "${GITHUB_TOKEN}"
              mode: "push"
              branch: "main"
    ```

    <ParamField path="uri" type="string" required={true} toc={true}>
      Full URL to your GitHub repository (e.g., `https://github.com/your-org/your-repo`).
    </ParamField>

    <ParamField path="token" type="string" required={true} toc={true}>
      GitHub Personal Access Token with repository write permissions. Use an environment variable reference (e.g., `${GITHUB_TOKEN}`).
    </ParamField>

    <ParamField path="mode" type="'push' | 'pull-request'" required={false} toc={true}>
      How to publish changes: `push` commits directly to the branch, `pull-request` opens a PR for review.
    </ParamField>

    <ParamField path="branch" type="string" required={false} toc={true}>
      Target branch for commits or pull requests.
    </ParamField>
  </Accordion>
</AccordionGroup>

#### `metadata`

Specify metadata for an individual SDK. Alternatively, you can [configure metadata globally for all SDKs](#metadata).

```yml title="generators.yml" {6-10}
groups: 
  ts-sdk:
    generators:
      - name: fernapi/fern-typescript-sdk
      ...
        metadata: 
          package-description: "Description of your SDK"
          email: "sdk@example.com"
          reference-url: "https://docs.example.com/sdks"
          license: "MIT"
```

<ParamField path="package-description" type="string" required={false} toc={true}>
  A brief description of what your generated SDK does and its key features. This appears in the `package.json` description field and package registry listings.
</ParamField>

<ParamField path="email" type="string" required={false} toc={true}>
  Contact email for the package maintainer or support team.
</ParamField>

<ParamField path="reference-url" type="string" required={false} toc={true}>
  URL pointing to comprehensive documentation, API reference, or getting started guide for the SDK.
</ParamField>

<ParamField path="author" type="string" required={false} toc={true}>
  Name of the individual developer, team, or organization that created and maintains the SDK.
</ParamField>

<ParamField path="license" type="'MIT' | 'Apache-2.0' | 'Custom License Name'" required={false} toc={true}>
  Software license for the generated SDK.
</ParamField>

#### `autorelease`

Enable or disable [Fern Autorelease](/learn/sdks/overview/autorelease) for an individual SDK. Alternatively, you can [configure autorelease globally for all SDKs](#autorelease-1).

```yml title="generators.yml" {6}
groups:
  ts-sdk:
    generators:
      - name: fernapi/fern-typescript-sdk
      ...
        autorelease: true
```

<ParamField path="autorelease" type="boolean | object" default={false} required={false} toc={true}>
  Set to `true` to enable Autorelease for this generator, `false` to disable it. Per-generator settings override the global [`autorelease`](#autorelease-1) configuration.
</ParamField>

<Accordion title="Enable with pull-based detection">
  Configure a cron schedule to periodically fetch and check for spec changes for this generator:

  ```yml title="generators.yml" {6-8}
  groups:
    ts-sdk:
      generators:
        - name: fernapi/fern-typescript-sdk
        ...
          autorelease:
            cron:
              schedule: "0 */6 * * *"  # Every 6 hours
  ```

  <ParamField path="cron.schedule" type="string" required={true} toc={true}>
    A cron expression defining how often to check for spec changes. Uses standard cron syntax.
  </ParamField>
</Accordion>

#### `snippets`

Configures snippets for a particular generator.

```yml title="generators.yml" {6-8}
groups: 
  ts-sdk:
    generators:
      - name: fernapi/fern-typescript-sdk
      ...
        snippets: 
          path: "./snippets"
```

<ParamField path="path" type="string" required={true} toc={true}>
  The path to the generated snippets file.
</ParamField>

#### Override API authentication settings

Override authentication settings in your API spec for a specific SDK using the `api` configuration.

<AccordionGroup>
  <Accordion title="Single authentication scheme">
    Reference a pre-defined authentication scheme by name.

    ```yml title="generators.yml" {6-7}
    groups: 
      ts-sdk:
        generators:
          - name: fernapi/fern-typescript-sdk
          ...
            api:
              auth: "bearer-token"
    ```

    <ParamField path="auth" type="string | { scheme: string }" required={false} toc={true}>
      The authentication scheme to use. Can be either a string reference (`"bearer-token"`) or scheme object (`scheme: "bearer-token"`).
    </ParamField>
  </Accordion>

  <Accordion title="Multiple authentication options">
    Allow users to authenticate with any of several methods:

    ```yml title="generators.yml" {6-12}
    groups: 
      ts-sdk:
        generators:
          - name: fernapi/fern-typescript-sdk
          ...
            api:
              auth:
                any:
                  - "api-key"
                  - "bearer-token"
                  - scheme: "oauth-flow"
    ```

    <ParamField path="any" type="list<string | { scheme: string }>" required={true} toc={true}>
      A list of authentication schemes where users can choose any one method. Each item can be either a string reference (`"api-key"`) or scheme object (`scheme: "api-key"`).
    </ParamField>
  </Accordion>

  <Accordion title="Custom authentication schemes">
    Define a custom authentication schemes using `auth-schemes`. You define a name for your custom scheme, and then specify the authentication method (`header`, `basic`, `bearer`, or `oauth`).

    ```yml title="generators.yml" {8-12}
    groups: 
      ts-sdk:
        generators:
          - name: fernapi/fern-typescript-sdk
          ...
            api:
              auth-schemes:
                bearer:  # User-defined name for your auth schema
                  scheme: "bearer"
                  token:
                    name: "token"
                    env: "BEARER_TOKEN"
    ```

    <AccordionGroup>
      <Accordion title="Header authentication">
        Configure authentication using custom HTTP headers, such as API keys or tokens.

        ```yaml
        auth-schemes:
          api-key: # User-defined scheme name
            name: "API Key Authentication"
            header: "X-API-Key"
            type: "string"
            prefix: "ApiKey "
            env: "MY_API_KEY" # SDK will auto-scan this environment variable
        ```

        <ParamField path="header" type="string" required={true}>
          The name of the HTTP header to use for authentication.
        </ParamField>

        <ParamField path="name" type="string" required={false}>
          A descriptive name for this authentication scheme.
        </ParamField>

        <ParamField path="type" type="string" default="string">
          The type of the header value.
        </ParamField>

        <ParamField path="prefix" type="string" required={false}>
          A prefix to prepend to the header value (e.g., `"Bearer "` or `"Token "`).
        </ParamField>

        <ParamField path="env" type="string" required={false}>
          Environment variable name containing the authentication value. When specified, the generated SDK will automatically scan for this environment variable at initialization.
        </ParamField>
      </Accordion>

      <Accordion title="Basic authentication">
        Configure HTTP Basic authentication using username and password credentials.

        ```yaml
        auth-schemes:
          basic-auth: # User-defined scheme name
            scheme: basic
            username:
              name: "Username"
              env: "BASIC_AUTH_USERNAME" # SDK will auto-scan this environment variable
            password:
              name: "Password"
              env: "BASIC_AUTH_PASSWORD" # SDK will auto-scan this environment variable
        ```

        <ParamField path="scheme" type="'basic'" required={true}>
          Must be set to `"basic"` for Basic authentication schemes.
        </ParamField>

        <ParamField path="username" type="object" required={false}>
          Configuration for the username credential.
        </ParamField>

        <ParamField path="username.name" type="string" required={false}>
          Custom parameter name for the username in the generated SDK. If not specified, defaults to `"username"`. Use this to provide more descriptive or domain-specific parameter names like `"clientId"`, `"userEmail"`, or `"merchantId"`.
        </ParamField>

        <ParamField path="password" type="object" required={false}>
          Configuration for the password credential.
        </ParamField>

        <ParamField path="password.name" type="string" required={false}>
          Custom parameter name for the password in the generated SDK. If not specified, defaults to `"password"`. Use this to provide more descriptive or domain-specific parameter names like `"clientSecret"`, `"apiKey"`, or `"merchantKey"`.
        </ParamField>

        <ParamField path="username.env, password.env" type="string" required={false}>
          Environment variable name that the SDK will automatically scan for the username or password value. When this environment variable is present, users don't need to explicitly provide the username parameter. Follow naming conventions like `YOUR_APP_USERNAME` or `SERVICE_CLIENT_ID`.
        </ParamField>
      </Accordion>

      <Accordion title="Bearer Token Authentication">
        Configure Bearer token authentication for API access.

        ```yaml
        auth-schemes:
          bearer-token: # User-defined scheme name
            scheme: bearer
            token:
              name: "Access Token"
              env: "BEARER_TOKEN" # SDK will auto-scan this environment variable
        ```

        <ParamField path="scheme" type="'bearer'" required={true}>
          Must be set to `"bearer"` for Bearer token authentication schemes.
        </ParamField>

        <ParamField path="token" type="object" required={false}>
          Configuration for the bearer token.
        </ParamField>

        <ParamField path="token.name" type="string" required={false}>
          A descriptive name for the token.
        </ParamField>

        <ParamField path="token.env" type="string" required={false}>
          Environment variable name containing the bearer token. When specified, the generated SDK will automatically scan for this environment variable at initialization.
        </ParamField>
      </Accordion>

      <Accordion title="OAuth Client Credentials">
        <Note>
          For Fern Definition, you can configure OAuth authentication either in `generators.yml` or [directly in your `api.yml` file](/api-definitions/ferndef/authentication#oauth-client-credentials). For OpenAPI, [OAuth must be configured in `generators.yml`](/api-definitions/openapi/authentication#oauth-client-credentials).
        </Note>

        Configure OAuth 2.0 client credentials authentication. Optionally configure a `refresh-token` endpoint for token renewal without re-authentication.

        ```yaml title="generators.yml" maxLines=10
        auth-schemes:
          my-oauth: # User-defined scheme name
            scheme: oauth
            type: client-credentials
            scopes:
              - "read:users"
              - "write:users"
            client-id-env: "OAUTH_CLIENT_ID" # SDK will auto-scan this environment variable
            client-secret-env: "OAUTH_CLIENT_SECRET" # SDK will auto-scan this environment variable
            token-prefix: "Bearer"
            token-header: "Authorization"
            get-token:
              endpoint: "auth.get_token"
              request-properties:
                client-id: "clientId"
                client-secret: "clientSecret"
                scopes: "scope"
              response-properties:
                access-token: "access_token"
                expires-in: "expires_in"
                refresh-token: "refresh_token"
            refresh-token:
              endpoint: "auth.refresh_token"
              request-properties:
                refresh-token: "refreshToken"
              response-properties:
                access-token: "access_token"
                expires-in: "expires_in"
                refresh-token: "refresh_token"
        ```

        <ParamField path="scheme" type="'oauth'" required={true}>
          Must be set to `"oauth"` for OAuth authentication schemes.
        </ParamField>

        <ParamField path="type" type="'client-credentials'" required={true}>
          The OAuth 2.0 grant type. Currently only `"client-credentials"` is supported.
        </ParamField>

        <ParamField path="scopes" type="list of strings" required={false}>
          OAuth scopes to request when obtaining access tokens (e.g., `"read:users"`, `"write:orders"`).
        </ParamField>

        <ParamField path="client-id-env" type="string" required={false}>
          Environment variable name containing the OAuth client ID. When specified, the generated SDK will automatically scan for this environment variable at initialization.
        </ParamField>

        <ParamField path="client-secret-env" type="string" required={false}>
          Environment variable name containing the OAuth client secret. When specified, the generated SDK will automatically scan for this environment variable at initialization.
        </ParamField>

        <ParamField path="token-prefix" type="string" default="Bearer">
          Prefix added to the access token in the Authorization header (e.g., `"Bearer"` results in `"Authorization: Bearer <token>"`). Useful when your API expects a custom format.
        </ParamField>

        <ParamField path="token-header" type="string" default="Authorization">
          HTTP header name used to send the access token. Defaults to `"Authorization"` but can be customized if your API uses a different header (e.g., `"X-API-Token"`).
        </ParamField>

        ##### `get-token`

        Specifies the endpoint that exchanges client credentials for an access token. This endpoint is called automatically when the SDK client is initialized.

        ```yaml title="generators.yml"
        get-token:
          endpoint: "auth.get_token"
          request-properties:
            client-id: "clientId"
            client-secret: "clientSecret"
          response-properties:
            access-token: "access_token"
            expires-in: "expires_in"
        ```

        <ParamField path="endpoint" type="string" required={true}>
          The endpoint that issues access tokens, such as `'auth.get_token'`.
        </ParamField>

        <ParamField path="request-properties" type="object" required={false}>
          Maps OAuth parameter names to your API's request field names. Use this when your token endpoint expects different field names than the OAuth standard (e.g., your API uses `clientId` instead of `client_id`).
        </ParamField>

        <ParamField path="request-properties.client-id" type="string" required={false}>
          The request field name for the client ID in your API (e.g., `"clientId"`, `"client_id"`).
        </ParamField>

        <ParamField path="request-properties.client-secret" type="string" required={false}>
          The request field name for the client secret in your API (e.g., `"clientSecret"`, `"client_secret"`).
        </ParamField>

        <ParamField path="request-properties.scopes" type="string" required={false}>
          The request field name for scopes in your API (e.g., `"scope"`, `"scopes"`).
        </ParamField>

        <ParamField path="response-properties" type="object" required={false}>
          Maps your API's response field names to OAuth standard names. Use this when your API returns tokens with different field names (e.g., `accessToken` instead of `access_token`).
        </ParamField>

        <ParamField path="response-properties.access-token" type="string" required={false}>
          The response field name for the access token in your API (e.g., `"accessToken"`, `"access_token"`).
        </ParamField>

        <ParamField path="response-properties.expires-in" type="string" required={false}>
          The response field name for token expiration time in seconds (e.g., `"expiresIn"`, `"expires_in"`). When present, the SDK automatically refreshes tokens before expiration.
        </ParamField>

        <ParamField path="refresh-token" type="string" required={false}>
          The response field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`). Required if using the `refresh-token` flow.
        </ParamField>

        ##### `refresh-token`

        Specifies the endpoint that exchanges a refresh token for a new access token. When configured, the SDK automatically uses this endpoint to renew expired tokens without re-sending credentials. If not configured, the SDK will re-authenticate using `get-token` when tokens expire.

        ```yaml title="generators.yml"
        refresh-token:
          endpoint: "auth.refresh_token"
          request-properties:
            refresh-token: "refreshToken"
          response-properties:
            access-token: "access_token"
            expires-in: "expires_in"
        ```

        <ParamField path="endpoint" type="string" required={true}>
          The endpoint that refreshes access tokens (e.g., `"POST /oauth/refresh"` or `"auth.refreshToken"`).
        </ParamField>

        <ParamField path="request-properties" type="object" required={false}>
          Maps OAuth parameter names to your API's request field names for the refresh flow.
        </ParamField>

        <ParamField path="request-properties.refresh-token" type="string" required={true}>
          The request field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`).
        </ParamField>

        <ParamField path="response-properties" type="object" required={false}>
          Maps your API's refresh response field names to OAuth standard names.
        </ParamField>

        <ParamField path="response-properties.access-token" type="string" required={false}>
          The response field name for the new access token (e.g., `"accessToken"`, `"access_token"`).
        </ParamField>

        <ParamField path="response-properties.expires-in" type="string" required={false}>
          The response field name for the new token's expiration time in seconds (e.g., `"expiresIn"`, `"expires_in"`).
        </ParamField>

        <ParamField path="response-properties.refresh-token" type="string" required={false}>
          The response field name if your API issues a new refresh token with each refresh (token rotation).
        </ParamField>
      </Accordion>
    </AccordionGroup>
  </Accordion>
</AccordionGroup>

### `reviewers`

Set code reviewers globally for all SDKs. Alternatively, you can [configure reviewers for individual SDKs](#reviewers).

```yaml title="generators.yml"
reviewers:
  teams:
    - name: "sdk-team"
    - name: "api-team"
  users:
    - name: "john-doe"
    - name: "jane-smith"
```

<ParamField path="teams" type="list of strings" required={false} toc={true}>
  GitHub team names that should review generated code.
</ParamField>

<ParamField path="users" type="list of strings" required={false} toc={true}>
  GitHub users that should review generated code.
</ParamField>

<ParamField path="teams.name" type="string" required={true} toc={true}>
  Name of a GitHub team.
</ParamField>

<ParamField path="users.name" type="string" required={true} toc={true}>
  Name of a GitHub user.
</ParamField>