---
title: @specdiff/core API Reference
description: Complete API reference for @specdiff/core: types, diff functions, rule helpers, formatters, pointer utilities, and ref resolution.
url: https://pr-1-b9e16090e83d.thally.app/specdiff/core-api
---

# @specdiff/core API Reference

Complete API reference for @specdiff/core: types, diff functions, rule helpers, formatters, pointer utilities, and ref resolution.

`@specdiff/core` is the zero-dependency diffing engine for Specdiff. It exports
types, constants, diff functions, rule helpers, formatters, and pointer utilities.
Install it with:

```bash
npm install @specdiff/core
```

All exports are ESM only. Node.js 22 or later is required.

## Types

### `Severity`

```ts
type Severity = "breaking" | "warning" | "info";
```

The three levels assigned to every detected change.

### `Direction`

```ts
type Direction = "request" | "response" | "neutral";
```

Controls how direction-dependent rules resolve their severity. For OpenAPI diffs,
direction is derived automatically per context (request for parameters and request
bodies, response for responses). For JSON Schema diffs, pass `direction` in
`DiffOptions` (defaults to `"neutral"`).

### `DocumentKind`

```ts
type DocumentKind = "openapi" | "json-schema";
```

### `RuleCode`

```ts
type RuleCode = keyof typeof RULES;
```

A union of all 45 rule code strings (for example `"type-changed"`,
`"endpoint-removed"`, `"enum-value-added"`).

### `FailThreshold`

```ts
type FailThreshold = Severity | "none";
```

Used by `exceedsThreshold`. The value `"none"` means no severity level triggers
a failure.

### `RuleInfo`

```ts
interface RuleInfo {
  code: RuleCode;
  defaultSeverity: Severity;
  title: string;
  description: string;
  remediation: string;
  appliesTo: DocumentKind | "both";
}
```

Metadata for a single rule in the catalogue.

### `SchemaChange`

```ts
interface SchemaChange {
  code: RuleCode;
  severity: Severity;
  path: string;
  message: string;
  before?: unknown;
  after?: unknown;
}
```

A single detected change. The `path` field is an RFC 6901 JSON pointer, always
prefixed with `#`. The optional `before` and `after` fields carry the relevant
values when applicable.

### `DiffSummary`

```ts
interface DiffSummary {
  breaking: number;
  warning: number;
  info: number;
  total: number;
}
```

Per-severity counts of changes.

### `DiffResult`

```ts
interface DiffResult {
  changes: SchemaChange[];
  summary: DiffSummary;
  maxSeverity: Severity | null;
  kind: DocumentKind;
}
```

The main return type from all diff functions. `maxSeverity` is `null` when no
changes were detected.

### `DiffOptions`

```ts
interface DiffOptions {
  ignoreRules?: RuleCode[];
  overrides?: Partial<Record<RuleCode, Severity>>;
  ignorePaths?: string[];
  direction?: Direction;
}
```

- `ignoreRules` -- rule codes whose changes are dropped from results.
- `overrides` -- override the severity of specific rules.
- `ignorePaths` -- JSON pointer prefixes; changes at or beneath these paths are
  dropped.
- `direction` -- applies to JSON Schema diffs only (defaults to `"neutral"`).
  Ignored for OpenAPI diffs, which derive direction automatically.

### `FormatTextOptions`

```ts
interface FormatTextOptions {
  color?: boolean;
}
```

When `color` is `true`, `formatText` includes ANSI colour codes. Defaults to
`false`.

### `Resolved`

```ts
interface Resolved {
  schema: unknown;
  ref: string | undefined;
  unresolved: string | undefined;
}
```

Returned by `resolveNode`. The `schema` field is the resolved value, `ref` is
the final `$ref` string that was followed, and `unresolved` is set when a ref
could not be resolved (remote or missing).

---

## Constants

### `SEVERITY_ORDER`

```ts
const SEVERITY_ORDER: { breaking: 0; warning: 1; info: 2 };
```

Numeric ordering for severity comparison. Lower numbers are more severe.

### `SEVERITIES`

```ts
const SEVERITIES: readonly Severity[];
// ["breaking", "warning", "info"]
```

The three severity levels in order from most to least severe.

### `RULES`

```ts
const RULES: Record<RuleCode, RuleInfo>;
```

The complete 45-rule catalogue, keyed by rule code. Each value is a `RuleInfo`
object. See the [rules reference](/specdiff/rules) for the full table.

### `DIRECTION_SEVERITY`

```ts
const DIRECTION_SEVERITY: Partial<Record<RuleCode, Record<Direction, Severity>>>;
```

Twelve rules whose severity depends on direction. For example,
`required-added` is `breaking` for `request` but `info` for `response`. Rules
not present in this map always use their `defaultSeverity`.

---

## Diff functions

### `diffJsonSchema`

```ts
function diffJsonSchema(
  before: unknown,
  after: unknown,
  options?: DiffOptions,
): DiffResult;
```

Compares two JSON Schema documents. The `options.direction` parameter defaults to
`"neutral"` and controls how direction-dependent rules resolve severity.

### `diffOpenApi`

```ts
function diffOpenApi(
  before: unknown,
  after: unknown,
  options?: DiffOptions,
): DiffResult;
```

Compares two OpenAPI 3.x documents. Direction is derived automatically per
context (request for parameters and request bodies, response for response
schemas). The `options.direction` field is ignored.

### `diffDocuments`

```ts
function diffDocuments(
  before: unknown,
  after: unknown,
  options?: DiffOptions,
): DiffResult;
```

Auto-detects the document kind: if either document has a string `openapi` key it
delegates to `diffOpenApi`, otherwise to `diffJsonSchema`. This is the
recommended entry point when the document type is not known ahead of time.

### `detectDocumentKind`

```ts
function detectDocumentKind(document: unknown): DocumentKind;
```

Returns `"openapi"` if the document is an object with a string `openapi` key,
otherwise `"json-schema"`.

### `exceedsThreshold`

```ts
function exceedsThreshold(
  result: DiffResult,
  threshold: FailThreshold,
): boolean;
```

Returns `true` when `result.maxSeverity` is at or above `threshold`. A threshold
of `"none"` always returns `false`.

### `finalize`

```ts
function finalize(
  rawChanges: readonly SchemaChange[],
  kind: DocumentKind,
  options?: DiffOptions,
): DiffResult;
```

Applies `ignoreRules`, `ignorePaths`, and `overrides` from options, sorts the
changes, and computes the summary. This is used internally by the diff functions
but is exported for scenarios where you need to post-process raw changes.

### `summarize`

```ts
function summarize(changes: readonly SchemaChange[]): DiffSummary;
```

Computes per-severity counts from an array of changes.

### `compareChanges`

```ts
function compareChanges(a: SchemaChange, b: SchemaChange): number;
```

Sort comparator for `SchemaChange` arrays. Sorts by severity (breaking first),
then path, then code, then message. Uses code-point comparison for locale
independence.

---

## Rules functions

### `listRules`

```ts
function listRules(): RuleInfo[];
```

Returns every rule in the catalogue as an array, in catalogue order.

### `explainRule`

```ts
function explainRule(code: string): RuleInfo | undefined;
```

Looks up a rule by its code string. Returns `undefined` for unknown codes.

### `isRuleCode`

```ts
function isRuleCode(value: string): value is RuleCode;
```

Type guard that narrows a string to `RuleCode`.

### `severityFor`

```ts
function severityFor(code: RuleCode, direction: Direction): Severity;
```

Returns the effective severity for a rule in the given direction. Consults
`DIRECTION_SEVERITY` first, then falls back to `RULES[code].defaultSeverity`.

---

## Formatters

### `formatText`

```ts
function formatText(
  result: DiffResult,
  options?: FormatTextOptions,
): string;
```

Produces a human-readable text report grouped by severity. Starts with a summary
line, then one block per severity level present. The output ends with a single
newline. Pass `{ color: true }` for ANSI colour codes.

### `formatMarkdown`

```ts
function formatMarkdown(result: DiffResult): string;
```

Produces a GitHub-flavoured Markdown report with a heading that includes the
document kind (for example `## Specdiff report (OpenAPI)` or
`## Specdiff report (JSON Schema)`), a severity summary table, and a
`| Rule | Path | Message |` table for each severity present.

### `formatJson`

```ts
function formatJson(result: DiffResult): string;
```

Returns `JSON.stringify(result, null, 2)` with a trailing newline.

### `summaryLine`

```ts
function summaryLine(result: DiffResult): string;
```

Returns a single line such as `"29 changes: 13 breaking, 7 warning, 9 info"` or
`"No changes detected."`.

### `formatRulesMarkdown`

```ts
function formatRulesMarkdown(): string;
```

Returns the full rule catalogue formatted as a Markdown table with columns for
Code, Default severity, Applies to, and Description.

---

## JSON Pointer helpers

Utilities for working with RFC 6901 JSON pointers. Specdiff uses `#`-prefixed
pointers throughout.

### `escapePointerSegment`

```ts
function escapePointerSegment(segment: string | number): string;
```

Escapes a single pointer segment per RFC 6901: `~` becomes `~0` and `/` becomes
`~1`.

### `unescapePointerSegment`

```ts
function unescapePointerSegment(segment: string): string;
```

Reverses escaping. Decodes `~1` before `~0` as required by the RFC.

### `joinPointer`

```ts
function joinPointer(
  base: string,
  ...segments: Array<string | number>
): string;
```

Appends escaped segments to a base pointer. For example,
`joinPointer("#/paths", "/pets")` returns `"#/paths/~1pets"`.

### `parsePointer`

```ts
function parsePointer(pointer: string): string[];
```

Splits a pointer into unescaped segments. For example,
`parsePointer("#/a~1b/c")` returns `["a/b", "c"]`. Throws an `Error` if the
pointer does not start with `/` or `#/`.

### `normalizePointer`

```ts
function normalizePointer(pointer: string): string;
```

Normalizes user-supplied pointer prefixes so that `"paths/x"`, `"/paths/x"`, and
`"#/paths/x"` all become `"#/paths/x"`. Trailing slashes are trimmed.

### `pointerHasPrefix`

```ts
function pointerHasPrefix(pointer: string, prefix: string): boolean;
```

Segment-aware prefix check. The prefix is normalized before comparison.

### `resolvePointer`

```ts
function resolvePointer(document: unknown, pointer: string): unknown;
```

Walks a document by pointer segments. Returns `undefined` when any segment cannot
be resolved. Handles both objects and arrays.

---

## Ref helpers

### `isLocalRef`

```ts
function isLocalRef(ref: string): boolean;
```

Returns `true` for local references (`#/...` or `#`).

### `resolveNode`

```ts
function resolveNode(
  document: unknown,
  node: unknown,
  maxDepth?: number,
): Resolved;
```

Follows a chain of local `$ref` pointers up to `maxDepth` (default 32). Returns
a `Resolved` object with the final schema, the last `$ref` that was followed,
and an `unresolved` field set when a ref could not be resolved (remote or
missing target). Uses Draft-07 semantics: sibling keywords next to `$ref` are
ignored.