Skip to content

Bind your first API spec

An API provider is a live binding to a description of your API. Adding one is how endpoints get into Tinspec — you do not import and then maintain a copy.

From the navigator’s API providers section, add a source. The first step is which kind of description your API has:

  • OpenAPI / REST — a URL (http://localhost:8080/v3/api-docs for springdoc, /openapi.json for FastAPI), a .json or .yaml file on disk, or Discover if you do not know the path.
  • gRPC service — server reflection, or a .proto file. Reflection is offered first because it needs no file at all.
  • GraphQL API — the endpoint’s own introspection query.
  • MCP server — its tools/list; each tool becomes an endpoint.

Whichever you pick, the add form also carries the poll interval for this source, defaulting to the global one in Settings → Endpoints. It is on the add form rather than buried in provider settings on purpose: for reflection, introspection and tool lists, that control is the whole difference between a binding and an import.

Tinspec fetches the description, resolves it, and the endpoints appear in the navigator grouped by their tags.

Give Tinspec the base URL of the service and let it discover the spec. It probes the well-known documentation locations — /openapi.json, /v3/api-docs, /swagger.json and the like — and offers what it finds.

This probes documentation endpoints only. It never guesses at resource paths, so it will not send traffic at your actual API looking for something that responds.

Mostly obvious, with one case worth saying out loud: a GraphQL endpoint is one root field (query.user), not one type. A type is not callable and a root field is — and since every root field POSTs to the same URL, identifying them by URL would collapse all of them onto one tab and one set of edits. gRPC works the same way, by Service/Method.

Each endpoint is a ready-to-send request: method, URL, path and query parameters typed from the description, headers, and a generated example body built from the request schema. Open one and the Docs view shows its parameters, body fields, and documented response codes.

Endpoints the document flags are flagged here too. A deprecated operation carries a badge. An operation marked x-internal is hidden by default — turn on Settings → Endpoints → Show internal endpoints to list them — and every surface that hides some says N internal hidden rather than silently showing a short list.

Tinspec polls the description on the interval you set per provider. When it moves:

  • new operations appear,
  • removed ones disappear,
  • changed ones update in place.

If the service goes offline, the last successfully fetched document is cached, so your endpoints keep working.

A file-backed OpenAPI spec is watched too. The tick is a cheap stamp check — the modified time and size of the root document and of every local $ref it reaches — so editing schemas/user.yaml beside your service runs the same refresh that a URL poll would. A remote $ref is deliberately not watched: nothing on this machine can watch it, and it falls back to the ordinary poll interval.

Changes are not silent. The Spec Changes view collects everything that moved since you last looked and explains each modified endpoint field by field — a parameter that became required, a response that changed shape, a body field that vanished. Acknowledging a change is always explicit: tick the row, or use Mark seen per provider. Opening an endpoint to look at it does not mark it as reviewed.

Changes are classified. The engine decides whether a change is breaking, direction-aware — tightening an input breaks callers, loosening an output breaks consumers — and each rule has a stable id, so the classification is not a matter of wording. The app then joins that to your own project and says who it breaks: which saved requests, chains, and overlays point at that operation. Rows are ordered impact-first, then breaking-first, and a plain new operation added with no impact is dropped rather than burying the rest.

One honest limit: this resolves against the endpoints that are live. A removed operation no longer exists to match against, so “DELETE /legacy was removed and two of your chains still call it” is the one sentence this feature cannot say.

Environments from the document’s servers

Section titled “Environments from the document’s servers”

An OpenAPI document usually declares several servers[] — production, staging, a sandbox. Provider settings → Overview offers Create environments from this spec’s servers, which derives a named environment per server with its URL as baseUrl. It never overwrites an environment you already made; a second run is a no-op.

What it does not do is retarget the generated endpoints, and the dialog says so. When a document declares servers[], Tinspec builds absolute endpoint URLs from the first of them, so {{baseUrl}} appears nowhere in those URLs and selecting one of these environments does not redirect them. What it does is supply {{baseUrl}} to requests you author or fork, to chains, and to the gateway base-URL field. (A document with no servers[] is the opposite case: there the environment’s baseUrl really is what decides where a request goes.)

A spec-generated endpoint is regenerated on every poll, but edits you make to one persist. Change its body, params, headers, or auth in Form view and Tinspec records an overlay — the field groups that differ from the generated request — as committable YAML in .tinspec/overlays/. The overlay is re-applied after every refresh.

A group can also record a removal: deleting a generated header or param is stored as “the user deleted this”, distinct from “the user never touched it”, so the deletion survives the next poll instead of being quietly regenerated.

The editor marks such an endpoint with an Edited chip and offers Reset to spec. If the spec changes underneath an edit you made, you get an amber banner with two choices — Keep edits or Reset to spec. Nothing is ever merged silently.

URL and method are deliberately not overlayable: they are the endpoint’s identity.

Send your first request.