---
title: "Review an API update"
description: "Carry a custom CLI workflow through an API addition, an edit conflict, and a breaking client change."
url: https://typeship.dev/docs/guides/review-an-api-update
markdown: https://typeship.dev/docs/guides/review-an-api-update.md
section: "Generations"
---
> ## Documentation index
> Fetch the documentation index at https://typeship.dev/llms.txt or every prose page and both generated references at https://typeship.dev/llms-full.txt.
> Append .md to any prose docs URL, or send Accept: text/markdown, for the markdown twin of that page.
> Select existing code examples with Accept-Code-Language: typescript, python, or go (one value), or add ?codeLanguage=python to a Markdown URL. The query parameter takes precedence. Unsupported values return the full docs with a notice.

# Review an API update

Carry a custom CLI workflow through an API addition, an edit conflict, and a breaking client change.

A linked repository Delivery carries API updates into the package your customers use. This walkthrough changes the fictional Parcel API, preserves a custom shipping-label command, resolves an overlapping edit, and repairs a breaking client change before accepting a Release.

You control the source changes and destination merges. A successful Generation produces files; a ready Draft has passed its required checks. Merging that checked Draft creates a Target Release. Publishing to a registry is a separate step.

## Prepare a linked CLI

You need Node.js 22 or later, npm, Git, `curl`, `jq`, a Typeship API key, and write access to two GitHub repositories. Install the [Typeship GitHub App](https://typeship.dev/docs/integrations/github) on both. Use repositories where you can review and merge the example changes.

1. Download the [Parcel lifecycle Definition](https://typeship.dev/examples/parcel-lifecycle/openapi.json) as `openapi.json` in your source repository and commit it. The three-operation API is fictional; its server is not a live shipping service.
2. [Link the repository](https://typeship.dev/docs/guides/add-to-an-existing-api-repo) to a Project. Select a CLI Target, set `cli.command_name` to `parcel`, and configure its repository Delivery to the destination repository's `cli` directory. Leave **Publish after merge** disabled for this walkthrough.
3. Generate the initial package, [select Draft version `1.0.0`](https://typeship.dev/docs/guides/publish#choose-the-draft-version), and merge it after release readiness and combined-package checks pass. Confirm `1.0.0` appears in the Target's Release history.
4. Require `Typeship – release readiness` and the Target's combined-package check in the destination's branch rules. Without required checks, GitHub can allow a failing Draft to merge.

Set the Project and Target IDs from the Console. The API key below belongs to Typeship; the workflow's local mock uses separate example credentials.

```bash
export TYPESHIP_PROJECT="prj_..."
export TYPESHIP_TARGET="tgt_..."
export TYPESHIP_TOKEN="<your-Typeship-API-key>"

typeship_api() {
  local request_path="$1"
  shift
  curl --fail-with-body -sS \
    -H "Authorization: Bearer $TYPESHIP_TOKEN" \
    -H "Content-Type: application/json" \
    "https://typeship.dev/api/v1$request_path" "$@"
}
```

Use separate checkouts for the source repository and the destination Draft. Run Definition edits below in the source checkout; run package edits in the Draft's `cli` directory.

## Add a field and a custom command

Add an optional `carrier` field to `Label`:

```bash title="Add a carrier"
node --input-type=module <<'JS'
import { readFileSync, writeFileSync } from "node:fs";
const spec = JSON.parse(readFileSync("openapi.json", "utf8"));
spec.components.schemas.Label.properties.carrier = { type: "string" };
writeFileSync("openapi.json", JSON.stringify(spec, null, 2) + "\n");
JS
```

Commit and review the source change, then merge it. Automatic generation can deliver the update, or request it explicitly:

```bash
typeship_api "/projects/$TYPESHIP_PROJECT/generations" -X POST
typeship_api "/targets/$TYPESHIP_TARGET/draft" > draft.json
jq '{version, head_revision, readiness, pull_request_url}' draft.json
```

Open the returned `pull_request_url` and check out that Draft. Expect the additive update to propose `1.1.0`. In its `cli` directory, add the four customer-authored files and executable registration from [Add a custom workflow](https://typeship.dev/docs/guides/custom-workflows#generate-and-add-the-workflow). Use the linked package already on this Draft; skip that guide's initial stateless generation command.

Also change the comment `Read the label status.&#x60; in &#x2A;*`src/resources/labels.ts`** to `Read the label status for our operations team.` Leave the method implementation intact. This customization gives the later documentation update an overlap to resolve.

Build and run the workflow's twelve local-mock tests, then commit its files, `package.json`, and the edited resource to the Draft. [Add a customer package check](https://typeship.dev/docs/guides/customize#configure-package-checks) named `parcel-label-workflow` with command `npm run test:workflow`, preserving existing generated, customer, and repository checks.

Generate again after updating the check configuration. Retrieve the Draft again and use its latest URL and head. Check-configuration changes can replace the candidate review; customer commits remain in the branch's ancestry.

```bash
typeship_api "/projects/$TYPESHIP_PROJECT/generations" -X POST
typeship_api "/targets/$TYPESHIP_TARGET/draft"
typeship_api "/targets/$TYPESHIP_TARGET/customizations"
```

Confirm that the combined package contains `carrier?: string`, the custom workflow files, the edited comment, and the `parcel-label` executable. Its checks must pass on the current `head_revision`. Merge the checked Draft and confirm Release `1.1.0` before continuing.

## Resolve an overlapping edit

Change the source operation's description:

```bash title="Update label documentation"
node --input-type=module <<'JS'
import { readFileSync, writeFileSync } from "node:fs";
const spec = JSON.parse(readFileSync("openapi.json", "utf8"));
spec.paths["/labels/{label_id}"].get.description = "Read the latest label state.";
writeFileSync("openapi.json", JSON.stringify(spec, null, 2) + "\n");
JS
```

Review and merge the source edit, generate again, then inspect customizations:

```bash
typeship_api "/projects/$TYPESHIP_PROJECT/generations" -X POST
typeship_api "/targets/$TYPESHIP_TARGET/customizations" > customizations.json
jq '{status, conflict_stage, conflicts, head_revision}' customizations.json
```

Expect `status: conflicted` and a generation conflict in `src/resources/labels.ts`. Both your accepted comment and the newly generated comment changed the same text. Current stays at `1.1.0`; successful generation alone does not authorize a Release.

Review the incoming file using the Generation ID under `input.next_generation_id`. For this example, accept its new description and discard the older custom comment in that resource. This selects the **whole incoming file**, so inspect all its changes first:

```bash
jq '{paths: ["src/resources/labels.ts"], choice: "generated",
     expected_head_revision: .head_revision}' customizations.json > resolution.json
typeship_api "/targets/$TYPESHIP_TARGET/customizations/reset" \
  -X POST --data-binary @resolution.json
```

A `409 stale_draft` means the Draft changed since inspection. Retrieve the current customizations and review them again before choosing. For a manual combination of both versions, edit and commit the resolved file on the Draft instead; see [conflict resolution](https://typeship.dev/docs/guides/customize#agent-example-inspect-resolve-recheck).

The workflow files remain present and checks run again. Once readiness passes for the resolved head, expect a documentation-only `1.1.1` update. Merge it and confirm the new Release.

## Repair a breaking client change

Rename the label-read operation while retaining its HTTP path:

```bash title="Rename the label method"
node --input-type=module <<'JS'
import { readFileSync, writeFileSync } from "node:fs";
const spec = JSON.parse(readFileSync("openapi.json", "utf8"));
spec.paths["/labels/{label_id}"].get.operationId = "retrieveLabel";
writeFileSync("openapi.json", JSON.stringify(spec, null, 2) + "\n");
JS
```

Review the source report before merging this intentional interface change. Generate the destination update and inspect its Draft and customizations again. The generated client now has `client.labels.retrieve()` in place of `client.labels.get()`. The preserved workflow still calls `get`, so its build fails and readiness stays red. Current remains `1.1.1`.

Expect a major version proposal of `2.0.0`. A compatible HTTP path does not make a renamed client method compatible for callers. Selecting `1.1.2` cannot waive the required major version and returns `422`.

On the destination Draft, replace both `client.labels.get(` calls in `src/label-workflow.ts` with `client.labels.retrieve(`. Rebuild and run `npm run test:workflow`, then commit the fix. Regenerate if needed to refresh the Draft. All twelve workflow behaviors should pass against the unchanged local mock.

Retrieve the latest Draft before merging. Confirm its version is `2.0.0` and every required check belongs to that `head_revision`. Merge it only after readiness passes.

## Verify the accepted package

```bash
typeship_api "/targets/$TYPESHIP_TARGET/releases" > releases.json
jq '.data[] | {id, version, generation_id, definition_revision_id,
              delivery_revision, final_package_hash, checks}' releases.json
```

The completed sequence has Releases `1.0.0`, `1.1.0`, `1.1.1`, and `2.0.0`. The conflicted Draft and failed build create no intermediate Release. Match the final `delivery_revision` to the destination merge and inspect that commit's workflow and executable registration. Release checks retain the checked Draft head; the delivery revision records the accepted merge commit.

Registry publication is separate from accepting these repository Releases. When you are ready to distribute the package, configure [publishing](https://typeship.dev/docs/guides/publish) and verify the Publication result for the accepted Release.

> **For AI agents:** Follow the latest Draft URL and head after every generation, configuration update, or conflict choice. Use `revision` as `expected_revision` for Draft version selection and `head_revision` as `expected_head_revision` for conflict choices. Require current package checks and inspect Release history after the authorized merge. Source preservation, successful generation, Release acceptance, and registry publication prove different outcomes.

## Sitemap

[Documentation index](https://typeship.dev/llms.txt)
