# From Collections to Contracts — Routebase

> Why a Postman or Insomnia collection is not an API contract, what an importer can infer from example data and what it cannot, and the work that is left after the import finishes.

Canonical page: https://routebase.dev/guides/openapi/importing-postman-and-insomnia-collections/
Chapter 8 of 10 · OpenAPI · Last reviewed 2026-09-13 · The Routebase Team

Teams usually arrive at OpenAPI holding something else, because a collection of requests already exists, it works, and converting it looks like a file format problem. It is not one, and knowing why saves a week of surprise.

## Two different kinds of document

A collection is a record of calls, because somebody made a request, it worked, and it was saved so that it could be made again. Everything in it is a concrete instance, meaning this URL, these headers, this body.

A contract is a set of statements about every call, not one of them. It says which fields are always present, which are optional, what the allowed values are and what happens when the request is rejected.

_Figure: An example is evidence that one call looked a certain way once, while a schema is a claim about every call, which is why the step between them is inference rather than translation._

The gap between the two is not notation, because the second document contains information that the first one never held.

## What an importer can work out

A good importer gets further than people expect, because the structure of a collection maps cleanly onto the structure of a document.

Requests become operations, since a method and a URL are exactly what an operation is. The path is recoverable, with the caveat that a concrete `/orders/7c9e6679` has to be generalised into `/orders/{orderId}` by something or someone. Folders become tags or a folder tree, and headers that appear on every request are candidates for security schemes or common parameters. Query parameters are visible in the URLs that were saved with each request.

And the response bodies produce schemas by inference, so an example that is an object with six fields becomes a schema with six properties, each typed from the value that happened to be there.

## What it cannot work out

Inference is the whole difficulty, because it can only see what the examples happened to contain.

**Optionality is invisible.** A field present in the one saved example looks required, and a field the API sometimes returns is simply absent from the schema.

**Null teaches nothing.** A field that was null in the example has no type at all, and an importer either guesses or leaves it open.

**Enums become strings.** A status that was `PAID` in the example becomes a string, and the other four values do not exist.

**Numeric shapes are coincidence.** A price that happened to be a round number becomes an integer, and the first decimal value breaks a generated client.

**Error responses are missing.** People save the calls that worked. A collection with forty requests usually contains no 401, no 422 and no 404, so the whole failure half of the contract has to be written.

**Scripts have no destination.** Pre-request scripts and test scripts describe behaviour around a call rather than the call itself, and a contract has nowhere to put them.

## The work after the import

The import is the cheap part, and the value comes from the pass afterwards. Four steps make the difference between a converted collection and a contract.

Go through the inferred schemas and decide what is required, since that is the single most valuable statement in the document and no importer can make it for you. Turn the strings that are really enums into enums, with the values and what they mean. Add the error responses, at minimum one rejected credential and one rejected request per operation. And write the descriptions, because a generated reference with no prose is a list of field names.

None of that needs to happen at once. An imported document that is honest about being incomplete is already better than a collection, since it can be validated, linted and checked against the running API.

## In Routebase

The specification wizard takes an OpenAPI file, a Postman collection or an Insomnia export, and the collection formats go through the same preview and the same validation as everything else. The product page for [migrating from Postman](/migrate-from-postman/) walks the move end to end, from the preview to the generated test cases.

_Screenshot: Collections come in through the same wizard as OpenAPI files, and the folder structure of the collection becomes the folder tree of the specification._

Where a schema was inferred rather than declared, the import says so in as many words, with the note that schemas were inferred from example data and may be incomplete. That is deliberate, because the failure mode worth avoiding is a document that looks finished and is not.

Afterwards the workspace is where the four steps above happen. The style guide will tell you which operations still lack a description and which endpoints have no error response, so the remaining work is a list rather than a feeling. The [Import and Export guide](https://docs.routebase.dev/import-export/) covers the flow, and our post on [migrating from Postman to an OpenAPI-first workflow](/blog/migrating-from-postman-to-openapi-first/) covers the move as a project rather than as an import.

## Frequently asked questions

### Can you convert a Postman collection to OpenAPI?

You can convert the structure, meaning the requests, their URLs, their methods, their headers and their folder layout. What cannot be converted is the part a collection never had, since a collection stores example bodies rather than schemas. An importer infers a shape from those examples, and the result is a starting point rather than a finished contract.

### What is the difference between a Postman collection and an OpenAPI file?

A collection records calls somebody made, while an OpenAPI document states what the API promises. The difference shows up in what each one can answer. A collection can tell you that this request returned that body once, and a contract can tell you which fields are always present, which are optional and what the error cases look like.

### What gets lost when you import a collection?

Everything the collection never recorded. Optional fields look required or vanish entirely depending on the example, and a field that happened to be null gets typed from that null. Enums become plain strings, and error responses exist only for the failures somebody happened to capture. Scripts and environment logic have no equivalent in a contract at all.

### Should we keep our Postman collection after moving to OpenAPI?

You can, and the thing to avoid is maintaining both as sources. Pick one place where a change is made and generate the other from it, since an OpenAPI document exports as a collection whenever somebody wants one. Two hand-maintained descriptions of the same API is the arrangement that produced the drift in the first place.

---

[Routebase](https://routebase.dev/) — [Sign up](https://app.routebase.dev/): Every account starts with a 14-day Pro trial — no credit card required.
