# Manage OpenAPI specs with Speakeasy
Source: https://speakeasy.com/docs/sdks/guides/publish-specs-to-api-registry

import { Callout } from "@/mdx/components";



<Callout type="info" title="Use this guide only for managing OpenAPI specs independent of generating SDKs.">

For the quickstart to set up SDKs, see the [SDK Quickstart](/docs/sdks/create-client-sdks).

</Callout>

This guide walks through the process of managing OpenAPI specs using the Speakeasy API Registry and CLI. This is also known as a "source-only workflow" as it only uses the sources feature of [Speakeasy workflows](/docs/speakeasy-reference/workflow-file).

## Prerequisites

- A Speakeasy account and CLI installed. Log in [here](https://app.speakeasy.com/) to create an account.
- An OpenAPI spec for the API

## Overview

To get started, create a GitHub repository. Something like `company-specs` or `company-openapi` are common repository names.

Initialize a new workflow file by running `speakeasy configure sources` and follow the prompts to add in the OpenAPI spec and any
[overlays](/docs/prep-openapi/overlays/create-overlays). Make sure to give the `source` a meaningful name as this will be the name used for the API Registry in the workspace dashboard.

A common repository structure will look like the following:

```yaml
company-specs
├── .speakeasy/
│   ├── workflow.yaml
├── specs
│   ├── openapi.yaml
│   ├── ...
├── overlays
│   ├── overlay.yaml
│   ├── ...
├── overlayed_specs          # This folder includes specs that have been modified by overlays
│   ├── openapi_modified.yaml
│   ├── ...
└── .gitignore
```

The workflow file will be generated in the `.speakeasy` folder and will look like the following:

```yaml
workflowVersion: 1.0.0
speakeasyVersion: latest
sources:
    my-api:             # This is the name of the source used in `speakeasy configure sources`
        inputs:
            - location: specs/openapi.yaml
        registry:
            location: registry.speakeasy.com/your-company/your-company/my-api
        outputs:
            - location: overlayed_specs/openapi_modified.yaml
targets: {}
```

## Publishing spec changes

Any time a new version of the OpenAPI spec should be published to the API Registry, run:

```bash
speakeasy run -s target
```

This will publish the spec to the API Registry as a new revision for the source `my-api`.

Optionally tag the revision of a spec by running:

```bash
speakeasy tag apply -n v0.0.2
```

This will tag the most recent revision of the spec with the tag `v0.0.2`.

## API Registry

This will show up as the latest revision in the API Registry tab in the dashboard.

![Registry Tab](/assets/guides/registry-tab.png)

The API Registry can be used to:
- Track changes to specs, view detailed change reports, and download past versions of the spec.
- Create a stable public URL for sharing a particular revision of the spec.
- Use the registry URI as a source for generating SDKs, for example: `registry.speakeasy.com/your-company/your-company/my-api`.

## Triggering downstream SDK generation

For teams that manage SDKs in separate repositories, the spec repo can trigger SDK generation in downstream repos when changes are made. This pattern is useful when:

- A central team manages the API specification
- Multiple SDK repositories need to be generated from the same spec
- SDK generation should be triggered automatically when the spec changes
- SDK PRs should be created in downstream repos for review before merging

### Architecture overview

```
┌─────────────────────────────────────────────────────────────────────────┐
│                           Spec Repository                               │
│  ┌─────────────┐    ┌─────────────────────────────────────────────┐    │
│  │ OpenAPI     │    │ GitHub Actions Workflow                     │    │
│  │ Spec        │───▶│ 1. Runs `speakeasy run` to tag spec         │    │
│  │ (PR change) │    │ 2. Triggers downstream SDK workflows        │    │
│  └─────────────┘    │ 3. Updates PR comment with status           │    │
│                     └─────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────────────┘
                                   │
                                   │ gh workflow run
                                   ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                        Downstream SDK Repos                             │
│  ┌──────────────────────────┐    ┌──────────────────────────┐          │
│  │ TypeScript SDK           │    │ Python SDK               │          │
│  │ - Pulls tagged spec      │    │ - Pulls tagged spec      │          │
│  │ - Generates SDK          │    │ - Generates SDK          │          │
│  │ - Creates PR             │    │ - Creates PR             │          │
│  └──────────────────────────┘    └──────────────────────────┘          │
└─────────────────────────────────────────────────────────────────────────┘
```

### Setting up downstream SDK repositories

Each downstream SDK repository needs a workflow that accepts `workflow_dispatch` inputs. After running `speakeasy configure github`, modify the generated workflow to accept these inputs:

```yaml
on:
  workflow_dispatch:
    inputs:
      force:
        description: "Force SDK regeneration"
        required: false
        default: "false"
      feature_branch:
        description: "Branch for SDK changes"
        required: false
      environment:
        description: "Environment variables (e.g., TAG=branch-name)"
        required: false
```

Pass these inputs to the workflow executor:

```yaml
jobs:
  generate:
    uses: speakeasy-api/sdk-generation-action/.github/workflows/workflow-executor.yaml@v15
    with:
      mode: pr
      force: ${{ inputs.force }}
      feature_branch: ${{ inputs.feature_branch }}
      environment: ${{ inputs.environment }}
    secrets:
      github_access_token: ${{ secrets.GITHUB_TOKEN }}
      speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }}
```

The SDK repo's `.speakeasy/workflow.yaml` should reference the registry with a `$TAG` variable:

```yaml
sources:
  my-api:
    inputs:
      - location: registry.speakeasyapi.dev/your-company/your-company/my-api@$TAG
```

### Required secrets

On the spec repository, configure these secrets:

| Secret | Description |
|--------|-------------|
| `SPEAKEASY_API_KEY` | Authenticates the Speakeasy CLI. Obtain from the [Speakeasy Platform](https://app.speakeasy.com) API Keys page. |
| `DOWNSTREAM_SDK_TOKEN` | A fine-grained GitHub PAT with `actions: write`, `contents: write`, and `pull-requests: write` permissions on all downstream SDK repos. |

On each downstream SDK repository:

| Secret | Description |
|--------|-------------|
| `SPEAKEASY_API_KEY` | Authenticates the Speakeasy CLI. Can be the same key as the spec repo or a separate key. |

### Example implementation

A complete working example is available in the [examples-downstream-spec-repo](https://github.com/speakeasy-api/examples-downstream-spec-repo) repository, which triggers SDK generation in:

- [examples-downstream-spec-sdk-typescript](https://github.com/speakeasy-api/examples-downstream-spec-sdk-typescript)
- [examples-downstream-spec-sdk-python](https://github.com/speakeasy-api/examples-downstream-spec-sdk-python)

The example includes workflows that:
- Trigger SDK generation when a PR is opened on the spec repo
- Update the spec PR with comments showing generation status and links to SDK PRs
- Automatically merge or close SDK PRs when the spec PR is merged or closed