# For API vendors

Vendor mode is for API vendors who publish an OpenAPI document. Each release
sends its API changes to Upseam. Upseam finds the code that uses them in your
users' repositories and delivers the change there: a dashboard issue, Slack
and, after the user's approval, a pull request.

```diagram title="How a change travels from your release to your users' code"
+----------------+
| your release   |  a tag in your repository
+----------------+
        |
        v
+----------------+
| change events  |  a diff of your OpenAPI document
+----------------+
        |
        v
+----------------+
| match          |  your SDKs, in your users' repositories
+----------------+
        |
        v
+----------------+
| your user      |  dashboard issue, Slack, then a tick
+----------------+
        |
        v
+----------------+
| pull request   |  the user reviews it
+----------------+
```

## What you get

- **Your changes reach the code that uses them.** Your users see them in
  their own repositories, with the affected lines, and not only in a changelog
  they may never read.
- **Nothing to write by hand.** The change events come from a diff of your
  OpenAPI document between two releases: removed operations, removed and
  renamed fields, removed parameters and parameters that became required,
  removed enum values, changed types and deprecations.
- **Your SDKs are found.** Upseam looks for the npm and PyPI packages you
  list in users' manifests and searches their code for the old names, paths
  and operation ids.
- **Users decide.** A change from a vendor is never patched automatically,
  unless it carries a recipe and the user turned on Simple fixes. Otherwise
  the user ticks it in the dashboard issue first.

## How a rename is found

A removed and an added field form a rename only when they sit in the same
object and have the same schema and the same `required` flag. Otherwise the
old field is a removal. When several fields could pair up, a rename needs at
least two pairs in the same object that swap the same leading words, such as
`provider_connect` to `app_connect` and `provider_share_owner` to
`app_share_owner`. One pair alone stays two removals.

A fix may use a new name only when the names share a non-generic word:
`html_body` to `html` can be patched, but `email` to `phone` needs a person.

## Recipes

A recipe tells Upseam how to fix a change without a model. It is data, never
code: a list of transforms from a closed set.

| Type | Fields | What Upseam edits |
| --- | --- | --- |
| `rename_field` | `from`, `to` | a key or keyword argument passed to a call on your SDK client |
| `rename_symbol` | `from`, `to`, `language` | a method called on your SDK client |
| `remove_field` | `field` | one property passed to a call on your SDK client, JavaScript and TypeScript only |
| `replace_model_id` | `from`, `to` | the `model` value passed to a call on your SDK client |
| `bump_pin` | `from` (a list), `to` | the pinned API version value your SDK configuration uses |

Keep recipes in a YAML or JSON file that maps event ids to recipes, and pass
it to `vendor publish`. Run `vendor publish --dry-run` to see the event ids.

```yaml title="recipes.yml"
rename-sendmessagerequest-html-body:
  transforms:
    - type: rename_field
      from: html_body
      to: html
  hints:
    - The field holds the same HTML.
```

```sh title="Publish with recipes"
npx @upseam/cli vendor publish --recipe recipes.yml
```

The CLI checks the file before it sends anything and prints the path of the
first fault, such as `rename-sendmessagerequest-html-body.transforms[0].to`.

Upseam applies a transform only at the places it matched in a user's
repository, and checks that the diff holds those edits and nothing else: no
other token, line, file, import or URL. A place where a transform is not safe,
such as a shorthand property or a call it cannot trace to your SDK, goes to a
person or the user's own model. Names that look security-related, such as
`token` or `verify`, and language globals are refused. Examples and hints are
never run: they reach the user's model only as quoted data.

A recipe fix is opened like any other simple fix: on its own when the user
turned on Simple fixes, and after the user's tick when they did not, which is
the default.

## Where to go next

:::cards Connect your API

- [Connect in 3 steps](vendor-connect.md)
  Run `vendor init`, merge two files and cut a tagged release.
- [Prove your packages](vendor-proof.md)
  Upseam delivers a package only when it can prove that you publish it.
- [Badge and docs snippet](vendor-badge.md)
  Tell your users that your API changes reach their code.
- [Analytics](vendor-analytics.md)
  What happened to each change you pushed, and which SDK versions are in use.
- [What vendors see about users](vendor-privacy.md)
  Aggregates only: ranges, no names and no code.

:::
