> This page is for SDKs, version Current (default).
> For other versions, use one of these documentation indexes:
> - Current (default): https://buildwithfern.com/learn/sdks/current/llms.txt
> - Legacy: https://buildwithfern.com/learn/sdks/legacy/llms.txt

> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://buildwithfern.com/learn/llms.txt.

# Publishing to Maven Central

> Learn how to publish your Fern-generated Java SDK to Maven Central. Complete guide covering authentication, GPG signatures, and automated releases.

> **Enterprise feature**
>
> This feature is available only for the [Enterprise plan](https://buildwithfern.com/pricing). To get started, reach out to [support@buildwithfern.com](mailto:support@buildwithfern.com).

Publish your public-facing Fern Java SDK to the [Maven Central registry](https://central.sonatype.com/). After following the steps on this
page, you'll have a versioned package published on Maven Central. To distribute
the SDK internally instead, generate to the local file system (optionally
[self-hosted](/learn/sdks/deep-dives/self-hosted)) and build a JAR with
[`fern generate --package`](/learn/cli-api-reference/cli-reference/sdk-commands#package).

> **Info**
>
> This page assumes that you have:
>
> * An initialized `fern` folder, a GitHub repository for your Java SDK, and a Java target in `sdk-config.yml`. See [Generating an SDK (Java)](/learn/sdks/generators/java/quickstart).

## Configure Maven Central publication

Update the Java target in `sdk-config.yml` to configure the target repository, publishing mode, and registry. Your `sdk-config.yml` [should live in your source repository](/learn/sdks/overview/project-structure) (or on your local machine), not the repository that contains your Java SDK code.

Optionally set the mode to control how Fern handles SDK publishing:

* `mode: release` (default): Fern generates code, commits to the default branch (or the `branch` you specify), and tags a release automatically
* `mode: pull-request` (recommended):  Fern generates code and creates a PR for you to review before release
* `mode: 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 [`output.github` reference](/learn/sdks/reference/sdk-config#github) for more information.

Set `output.delivery` to `github`, add the path to the GitHub repository containing your Java SDK, and set `output.publish.registry` to `maven`:

**`sdk-config.yml`**

```yaml title="sdk-config.yml"
targets:
  - language: java
    output:
      delivery: github
      github:
        repository: your-org/company-java
        mode: push  # or "pull-request"
        branch: your-branch-name  # Required for mode: push
      publish:
        registry: maven
```

## Set up Maven Central publishing authentication

#### Log into Maven Central

Log into [Maven Central](https://central.sonatype.com/) or create a new account.

#### Verify your namespace

1. Click on your username, then select **View Namespaces**. Click **Register New Namespace**.
2. Enter your company website or GitHub account in reverse domain name format and go through the verification process.

#### Configure Maven Coordinate

Add the namespace you verified in Maven Central to `package.groupId`, and set `package.artifactId` to your SDK's artifact name. Together these form the Maven coordinate customers use to reference your Java SDK in the Maven Central repository.

**`sdk-config.yml`**

```yaml {3-5} title="sdk-config.yml"
targets:
  - language: java
    package:
      groupId: com.company
      artifactId: sdk-name
    output:
      delivery: github
      github:
        repository: your-org/company-java
      publish:
        registry: maven
```

#### Generate user tokens

1. Back in Maven Central, click on your username, then select **View Account**
2. Click on **Generate User Token**, then click **Ok** to confirm
   generation. This will invalidate any existing token.

   > **Warning**
   >
   > Save your username and password tokens –  they won’t be displayed after you leave the page.

#### Configure Maven Central authentication token

Add `username: ${MAVEN_USERNAME}` and `password: ${MAVEN_PASSWORD}` to `output.publish` to tell Fern to use the `MAVEN_USERNAME` and `MAVEN_PASSWORD` environment variables for authentication when publishing to the Maven Central registry.

**`sdk-config.yml`**

```yaml {12-13} title="sdk-config.yml"
targets:
  - language: java
    package:
      groupId: com.company
      artifactId: sdk-name
    output:
      delivery: github
      github:
        repository: your-org/company-java
      publish:
        registry: maven
        username: ${MAVEN_USERNAME}
        password: ${MAVEN_PASSWORD}
```

## Generate GPG Signature

Next, set up code signing credentials by generating or identifying a GPG key ID, password, and secret key.  Maven Central requires all artifacts to be digitally signed with PGP/GPG keys.

> **Info**
>
> If you don't have gpg installed, you can download the binary from [https://gnupg.org/download/index.html](https://gnupg.org/download/index.html), or install it via package manager.

#### Find your key

If you already have a GPG key, you can list your keys:

```sh
gpg --list-secret-keys --keyid-format LONG
```

If you don't have a GPG key, you can generate a new one:

```sh
gpg --gen-key
```

You'll be prompted to create a new username and passphrase.

#### Export your key

Export your key so you can store it in an environment variable later on:

```sh
gpg --export-secret-keys --armor YOUR_KEY_ID
```

Be sure to replace `YOUR_KEY_ID` with the key ID of the key you want to export.

> **Info**
>
> More information is available on [Maven Central's GPG validation page](https://central.sonatype.org/publish/requirements/gpg/).

#### Configure GPG Signature

Add the `keyId`, `password`, and `secretKey` from the previous step to `output.publish.signature`:

**`sdk-config.yml`**

```yaml {14-17} title="sdk-config.yml"
targets:
  - language: java
    package:
      groupId: com.company
      artifactId: sdk-name
    output:
      delivery: github
      github:
        repository: your-org/company-java
      publish:
        registry: maven
        username: ${MAVEN_USERNAME}
        password: ${MAVEN_PASSWORD}
        signature:
          keyId: ${MAVEN_SIGNATURE_SECRET_KEY_ID}
          password: ${MAVEN_SIGNATURE_PASSWORD}
          secretKey: ${MAVEN_SIGNATURE_SECRET_KEY}
```

#### Upload your key to public key servers

Finally, upload your key to public key servers so Maven Central can access the signature:

```bash
# Upload to multiple key servers
gpg --keyserver keyserver.ubuntu.com --send-keys YOUR_KEY_ID
gpg --keyserver keys.openpgp.org --send-keys YOUR_KEY_ID
gpg --keyserver pgp.mit.edu --send-keys YOUR_KEY_ID
```

## Publish your SDK

Decide how you want to publish your SDK to Maven Central. You can use GitHub workflows for automated releases or publish directly via the CLI.

#### Release via a GitHub workflow

Set up a release workflow via [GitHub Actions](https://docs.github.com/en/actions/get-started/quickstart) so you can trigger new SDK releases directly from your source repository.

#### Set up authentication

Open your source repository in GitHub. Click on the **Settings** tab. Then, under the **Security** section, open **Secrets and variables** > **Actions**.

You can also use the url `https://github.com/<your-repo>/settings/secrets/actions`.

#### Add secret for your Fern API key

1. Select **New repository secret**.
2. Name your secret `FERN_TOKEN`.
3. 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 in `fern.config.json`.
4. Click **Add secret**.

#### Add secrets for Maven Central

Add the following repository secrets by selecting **New repository secret** for each:

1. `MAVEN_USERNAME` - Your Maven Central username
2. `MAVEN_PASSWORD` - Your Maven Central password
3. `MAVEN_SIGNATURE_SECRET_KEY_ID` - Your GPG key ID
4. `MAVEN_SIGNATURE_PASSWORD` - Your GPG passphrase
5. `MAVEN_SIGNATURE_SECRET_KEY` - Your GPG secret key

#### Set up a new workflow

Set up a CI workflow that you can manually trigger from the GitHub UI. In your repository, navigate to **Actions**. Select **New workflow**, then **Set up workflow yourself**. Add a workflow that's similar to this:

**`.github/workflows/publish.yml`**

```yaml title=".github/workflows/publish.yml" maxLines=0
name: Publish Java SDK

on:
  workflow_dispatch:
    inputs:
      version:
        description: "The version of the Java SDK that you would like to release"
        required: true
        type: string

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v4

      - name: Install Fern CLI
        run: npm install -g fern-api

      - name: Release Java SDK
        env:
          FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
          MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
          MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
          MAVEN_SIGNATURE_SECRET_KEY_ID: ${{ secrets.MAVEN_SIGNATURE_SECRET_KEY_ID }}
          MAVEN_SIGNATURE_PASSWORD: ${{ secrets.MAVEN_SIGNATURE_PASSWORD }}
          MAVEN_SIGNATURE_SECRET_KEY: ${{ secrets.MAVEN_SIGNATURE_SECRET_KEY }}
        run: |
          fern generate --target java --version ${{ inputs.version }} --log-level debug
```

> **Note**
>
> You can alternatively configure your workflow to execute `on: [push]`.

#### Regenerate and release your SDK

Navigate to the **Actions** tab, select the workflow you just created, 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 `mode` or set `mode: 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-request` or `mode: 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](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository) to initiate the publishing workflow in your SDK repository.

Once the workflow completes, you can view your new release by logging into Maven Central and navigating to **View Deployments**.

#### Release via CLI and environment variables

#### Set Maven environment variables

Set the Maven Central environment variables on your local machine:

```bash
export MAVEN_USERNAME=your-maven-username
export MAVEN_PASSWORD=your-maven-password
export MAVEN_SIGNATURE_SECRET_KEY_ID=your-gpg-key-id
export MAVEN_SIGNATURE_PASSWORD=your-gpg-passphrase
export MAVEN_SIGNATURE_SECRET_KEY=your-gpg-secret-key
```

#### Regenerate and release your SDK

Regenerate your SDK, specifying the version:

```bash
fern generate --target java --version <version>
```

The rest of the release process depends on your chosen mode:

* **Release mode (default):** If you didn't specify a `mode` or set `mode: 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-request` or `mode: 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](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository) to initiate the publishing workflow in your SDK repository.

Once the command completes, you can view your new release by logging into Maven Central and navigating to **View Deployments**.