Publishing to NuGet
Publish your public-facing Fern C#/.NET SDK to the NuGet registry. After following the steps on this page, you’ll have a versioned package published on NuGet.
Already publishing to NuGet?
If you’re using API key authentication, consider switching to OIDC (trusted publishing). See Migrating from API key to OIDC publishing for the steps.

This page assumes that you have:
- An initialized
fernfolder, a GitHub repository for your C#/.NET SDK, and a C#/.NET generator group ingenerators.yml. See Generating an SDK (C#/.NET).
Configure SDK package settings
Update your generators.yml file to configure the package name, output location, and client name for NuGet publishing. Your generators.yml should live in your source repository (or on your local machine), not the repository that contains your C#/.NET SDK code.
Configure output location
In the group for your C#/.NET SDK, change the output location from local-file-system (the default) to nuget to indicate that Fern should publish your package directly to the NuGet registry:
Configure GitHub publishing
Fern can automatically publish your SDK to NuGet via GitHub Actions. Configure your GitHub repository and publishing mode:
Optionally set the mode to control how Fern handles SDK publishing:
mode: release(default): Fern generates code, commits to the default branch (or thebranchyou specify), and tags a release automaticallymode: pull-request(recommended): Fern generates code and creates a PR for you to review before releasemode: push: Fern generates code and pushes to a branch you specify for you to review before release
You can also configure other settings, like the reviewers or license. Refer to the full github (generators.yml) reference for more information.
Configure authentication
Choose how you want to authenticate with NuGet when publishing. OpenID Connect (OIDC) authentication is recommended because it removes the need to manage long-lived API keys.
OIDC authentication (Recommended)
OIDC-based publishing (also known as “trusted publishing”) is the most secure way to publish. With OIDC, you don’t need to manage API keys — NuGet trusts your GitHub repository to publish directly via short-lived tokens scoped to your workflow.
Generate your SDK
Generate your SDK to create the GitHub Actions workflow with OIDC configuration:
This creates a .github/workflows/ci.yml file configured to use OIDC for NuGet publishing. The generated workflow includes:
- A
publishjob withpermissions: { contents: read, id-token: write } - The
NuGet/login@v1action, which exchanges a GitHub OIDC token for a short-lived NuGet API key (~1 hour) dotnet nuget pushusing the temporary API key from the login step
Alternatively, you can push your generators.yml changes and let the Fern GitHub Action generate the workflow for you.
Authorize your repository on nuget.org
Configure trusted publishing on nuget.org to allow your GitHub repository to publish:
- Go to nuget.org and click your user avatar
- Select Trusted Publishing > Create policy
- Fill in:
- Repository Owner: Your GitHub organization or username
- Repository: Your C# SDK repository name
- Workflow File:
ci.yml(filename only, without the.github/workflows/prefix)
- Choose the policy owner (organization profile or personal account). The policy applies to all packages owned by that profile.
Set the NUGET_USER GitHub Actions secret
The generated workflow requires a NUGET_USER secret containing your nuget.org profile name (not your email).
- Open your SDK repository on GitHub and go to Settings
- Navigate to Secrets and variables > Actions
- Click New repository secret
- Name it
NUGET_USERand enter your nuget.org profile name - Click Add secret
For private repositories, the trust policy starts as temporarily active for 7 days. It becomes permanent after the first successful login binds the repository and owner IDs. Run the publish workflow within that 7-day window.
Troubleshooting
“Unable to authenticate” error
Common causes:
- Workflow filename doesn’t match exactly (must be
ci.yml) - Trusted publisher configuration on nuget.org doesn’t match your repository settings
- A stale
NUGET_API_KEYsecret is interfering with OIDC authentication
Solution: Double-check your trusted publisher configuration on nuget.org matches your repository name and workflow filename exactly. Remove any old NUGET_API_KEY secret from your repository.
Private repository limitations
For private repositories, the trust policy is temporarily active for 7 days. It becomes permanent after the first successful login. Run the publish workflow within that window.
API key authentication (Legacy)
Generate a NuGet API key
-
Log into NuGet or create a new account
-
Click on your profile picture
-
Select API Keys, then Create
-
Name your key
-
Select Push > Push new packages and package versions as the Select Scopes type
-
Enter
*under Select Packages > Glob PatternReplacing an existing NuGet package
If you are overriding an existing package, select the relevant package instead of entering
*. -
Click Create

Publish your SDK
Your SDK will automatically be published to NuGet when you create a GitHub release with a version tag:
- Create a GitHub release with a version tag (for example,
v1.0.0) - The CI workflow will run automatically and publish to NuGet
- View your package on nuget.org to confirm the version
Alternative: Manual workflow dispatch
If you prefer to trigger publishes manually from your source repository, set up a release workflow via GitHub Actions.
Add secret for your Fern API key
- Open your source repository on GitHub and go to Settings
- Navigate to Secrets and variables > Actions
- Select New repository secret
- Name your secret
FERN_TOKEN - Add your Fern API key. If you don’t already have one, generate one by
running
fern token. By default, the API key is generated for the organization listed infern.config.json. - Click Add secret
If you use API key authentication, also add a NUGET_API_KEY secret with your NuGet API key.
Set up a new workflow
Create a CI workflow that you can manually trigger from the GitHub UI. Navigate to Actions > New workflow > Set up workflow yourself:
Regenerate and release your SDK
Navigate to the Actions tab, select the workflow, specify a version number, and click Run workflow. This regenerates your SDK.

The rest of the release process depends on your chosen mode:
-
Release mode (default): If you didn’t specify a
modeor setmode: release, no further action is required. Fern automatically tags the new release with your specified version number and initiates the publishing workflow in your SDK repository. -
Pull request or push mode: If you set
mode: pull-requestormode: push, Fern creates a pull request or pushes to a branch respectively. Review and merge the PR (pull-request) or branch (push), then tag a new release to initiate the publishing workflow in your SDK repository.
Once the workflow completes, view your new release by logging into NuGet and navigating to Manage Packages.
Alternative: Release via CLI and environment variables
Set NuGet environment variable
If you use API key authentication, set the NUGET_API_KEY environment variable on your local machine:
Regenerate and release your SDK
Regenerate your SDK, specifying the version:
The rest of the release process depends on your chosen mode:
-
Release mode (default): If you didn’t specify a
modeor setmode: release, no further action is required. Fern automatically tags the new release with your specified version number and initiates the publishing workflow in your SDK repository. -
Pull request or push mode: If you set
mode: pull-requestormode: push, Fern creates a pull request or pushes to a branch respectively. Review and merge the PR (pull-request) or branch (push), then tag a new release to initiate the publishing workflow in your SDK repository.
Once the workflow completes, view your new release by logging into NuGet and navigating to Manage Packages.
Migrating from API key to OIDC publishing
If you’re using API key authentication and want to migrate to OIDC, follow these steps.
Why migrate to OIDC
OIDC-based publishing (trusted publishing) removes security risks associated with long-lived API keys:
- Keys can be exposed in logs or configuration files
- Compromised keys can be used persistently until manually revoked
- Key rotation adds operational overhead
With OIDC, NuGet trusts your GitHub Actions workflow directly. The only secret required is NUGET_USER (your nuget.org profile name), which isn’t sensitive.
Prerequisites
Before migrating:
- A package published to NuGet
- A GitHub repository with GitHub Actions configured
- Access to your account on nuget.org
Choose your migration path
Path 1: Upgrade your generator (Recommended)
This is the easiest path if you can upgrade to a version of the C# SDK generator that supports OIDC.
When to use this path:
- You can upgrade to a Fern C# SDK generator version that supports OIDC
- You haven’t
.fernignore’d your CI workflow file
Configure trusted publishing on nuget.org
- Go to nuget.org and click your user avatar
- Select Trusted Publishing > Create policy
- Fill in:
- Repository Owner: Your GitHub organization or username
- Repository: Your C# SDK repository name
- Workflow File:
ci.yml(filename only, without the.github/workflows/prefix)
- Choose the policy owner (organization profile or personal account). The policy applies to all packages owned by that profile.
Update your generators.yml
Change the output.api-key field from ${NUGET_API_KEY} to OIDC:
Regenerate your SDK
Regenerate the SDK to update the CI workflow with OIDC configuration:
Locally:
Or via GitHub Actions:
Push your updated generators.yml and let the Fern GitHub Action regenerate the SDK.
This updates .github/workflows/ci.yml with the required OIDC permissions and switches to the NuGet/login@v1 action.
Add the NUGET_USER secret
The OIDC workflow requires a NUGET_USER secret containing your nuget.org profile name (not your email).
- Open your SDK repository on GitHub and go to Settings
- Navigate to Secrets and variables > Actions
- Click New repository secret
- Name it
NUGET_USERand enter your nuget.org profile name - Click Add secret
Path 2: Manual CI workflow update
Use this path if you can’t upgrade the generator or have customized your CI workflow.
When to use this path:
- You can’t upgrade due to breaking changes or compatibility concerns
- You’ve customized your CI workflow and added it to
.fernignore - Path 1 didn’t update your workflow file
Configure trusted publishing on nuget.org
Follow the same instructions as Path 1 to create a trusted publishing policy on nuget.org.
Update your CI workflow manually
Open your .github/workflows/ci.yml file and make these changes to the publish job:
Key changes from API key publishing:
- Adds
permissionswithid-token: writeandcontents: read - Adds the
NuGet/login@v1step that exchanges the OIDC token for a short-lived API key - Removes any
envblocks referencingNUGET_API_KEY
Add the NUGET_USER secret
The OIDC workflow requires a NUGET_USER secret. Follow the same instructions as Path 1, Step 4.
Verify your migration
After completing either migration path:
- Trigger a workflow run by creating a GitHub release with an alpha tag (e.g.,
v1.0.0-alpha) - Check the workflow logs to verify the publish step succeeds
- Verify your package by visiting it on nuget.org to confirm the new version published correctly
Migration troubleshooting
"Unable to authenticate" error
Common causes:
- Workflow filename doesn’t match exactly (must be
ci.ymlwith the.ymlextension) - Trusted publisher configuration on nuget.org doesn’t match your repository settings
- Missing
id-token: writeorcontents: readpermissions in workflow - A stale
NUGET_API_KEYsecret is interfering with OIDC authentication - Using self-hosted runners (not supported)
Solution: Double-check your trusted publisher configuration on nuget.org matches your repository name and workflow filename exactly. Remove any old NUGET_API_KEY secret.
Workflow still using NUGET_API_KEY
If your workflow continues using API key authentication:
- Verify you’ve removed any
envblocks referencingNUGET_API_KEYfrom the publish step - Ensure the
publishjob uses theNuGet/login@v1action - Ensure you’re using a generator version that supports OIDC (if using Path 1)
Private repository limitations
For private repositories, the trust policy starts as temporarily active for 7 days. It becomes permanent after the first successful login binds the repository and owner IDs. Run the publish workflow within that window.
