---
title: "Combine API documents"
description: "Turn related OpenAPI or GraphQL files into one logical Definition without forcing unrelated APIs into one Project."
url: https://typeship.dev/docs/guides/combine-api-specs
markdown: https://typeship.dev/docs/guides/combine-api-specs.md
section: "Get started"
---
> ## Documentation index
> Fetch the complete documentation index at https://typeship.dev/llms.txt (every page, one line each) or the full text at https://typeship.dev/llms-full.txt.
> Append .md to any docs URL, or send Accept: text/markdown, for the markdown twin of that page.

# Combine API documents

Turn related OpenAPI or GraphQL files into one logical Definition without forcing unrelated APIs into one Project.

A Project owns one logical Definition. That Definition may contain many files, but every operation should belong to one API product consumed, versioned, and released together.

## Choose the right shape

| What you have                                                             | What to do                                                                       |
| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| One OpenAPI entrypoint with external `$ref` files                         | Point Typeship at the entrypoint. Typeship resolves the graph itself.            |
| Several complete OpenAPI descriptions that form one consumer product      | Create and commit one combined entrypoint, then point Typeship at it.            |
| GraphQL SDL split across files                                            | Use whole-document `#import "./file.graphql"` directives from one root SDL file. |
| Independently consumed APIs with different audiences or release schedules | Create separate Projects. Do not join them to save configuration.                |

## Multi-file OpenAPI

OpenAPI already supports a document graph. Keep a small root file and reference path items or schemas by repository-relative path:

```yaml
openapi: 3.1.0
info:
  title: Acme API
  version: 1.0.0
paths:
  /customers:
    $ref: ./paths/customers.yaml
components:
  schemas:
    Customer:
      $ref: ./components/schemas/customer.yaml
```

Set this root as the Definition entrypoint. Typeship records every resolved source document in the Definition Revision, watches referenced-file-only changes, and reports Diagnostics against the original file coordinates. You do not need to bundle this graph for Typeship.

Repository references must stay inside the connected repository. URL references must stay on the entrypoint's origin.

See [Definitions](https://typeship.dev/docs/projects/definitions#sources) for the resolution boundary and [Spec compatibility](https://typeship.dev/docs/reference/spec-compatibility#references) for limits.

## Several complete OpenAPI descriptions

Two complete descriptions do not become one API merely because they share a directory. Combine them only when their operations should ship to the same consumers under one compatibility and release policy.

Typeship does not execute repository build commands. Produce the combined document in your workflow and commit it, or serve it at a stable URL.

For OpenAPI 3.x, one option is Redocly CLI's experimental [`join` command](https://redocly.com/docs/cli/commands/join):

```bash
npx @redocly/cli@latest lint payments.yaml
npx @redocly/cli@latest lint customers.yaml
npx @redocly/cli@latest join payments.yaml customers.yaml \
  --output openapi/typeship.yaml
```

Use `openapi/typeship.yaml` as the Definition entrypoint. Reproduce it in CI and fail when the committed file drifts.

Before joining, resolve conflicts in:

* paths and operation IDs;
* tags and schemas;
* security schemes; and
* server semantics.

Do not use `bundle` for this case. Bundling follows `$ref` values from one root; joining combines independent root descriptions.

## Multi-file GraphQL

Typeship composes whole SDL documents with simple import directives:

```graphql
# schema.graphql
#import "./customers.graphql"
#import "./payments.graphql"

schema {
  query: Query
  mutation: Mutation
}
```

Each imported file contributes its complete SDL. Named import syntax is not supported, and duplicate or conflicting types fail resolution.

GraphQL endpoint, authentication, environment, scalar, and title settings remain on the Definition.

## Keep APIs separate when ownership is separate

Use separate Projects when APIs have distinct consumers, authentication boundaries, version policies, owners, or release schedules. A shared repository does not require a shared Project. Each Project can point at a different entrypoint in that repository.

> **For AI agents:** Inspect the repository before proposing composition. Configure an existing root directly when files are connected by `$ref` or whole-document GraphQL imports. If several OpenAPI roots form one product, add a deterministic committed join step. Ask the API owner before joining independently consumed APIs.

## Sitemap

[Every page of these docs](https://typeship.dev/llms.txt)
