Swagger vs OpenAPI: Names, Versions, and Differences

Swagger vs OpenAPI explained: how the names relate, what changed from Swagger 2.0 to OpenAPI 3.0 and 3.1, and the same API written in both formats.

On this page

Swagger and OpenAPI are two names for one specification line. Up to version 2.0 the format was called the Swagger Specification. SmartBear Software donated it in 2015, and it continued as the OpenAPI Specification under the OpenAPI Initiative, a Linux Foundation project. Swagger 2.0 and OpenAPI 2.0 are the same document format; a file that starts with swagger: "2.0" is one. OpenAPI 3.0 and 3.1 are the newer versions, and they start with openapi: instead. Today "Swagger" mostly names SmartBear's tools, such as Swagger UI and Swagger Editor, which read OpenAPI files. What you usually need to know is which version your file is: 2.0, 3.0 or 3.1.

Names and versions at a glance

What people sayWhat it isFirst line of the file
Swagger 2.0, OpenAPI 2.0, "a Swagger file"The last version published under the Swagger nameswagger: "2.0"
OpenAPI 3.0First version under the OpenAPI name, with a new structureopenapi: 3.0.3 (or another 3.0.x)
OpenAPI 3.13.0 structure with full JSON Schema 2020-12 supportopenapi: 3.1.0 (or 3.1.1)
Swagger UI, Swagger EditorSmartBear tools that render and edit OpenAPI documentsNot a spec version
The version field on the first lines is the only reliable way to tell. A file named swagger.json can contain any of them.

The file name proves nothing. Many frameworks still serve an OpenAPI 3 document at /swagger.json or behind a Swagger UI page; getting the OpenAPI JSON from a Swagger UI page shows how to find the raw file. Open it and read the version field before choosing a validator, a code generator or a migration plan. The glossary entries for Swagger and OpenAPI cover the terms on their own. If Swagger UI refuses to render a file, Swagger UI unable to render this definition lists the version values it accepts. To write a spec and not only read one, APIForge vs Swagger Editor compares the two tools.

One API in Swagger 2.0 and OpenAPI 3.0

Here is a small Users API with two operations, bearer authentication and a nullable field, written once in each format. Both files pass validation with @apidevtools/swagger-parser, the library APIForge uses to parse specs.

YAMLusers.swagger2.yaml
swagger: "2.0"
info:
  title: Users API
  version: 1.0.0
host: api.example.com
basePath: /v1
schemes:
  - https
consumes:
  - application/json
produces:
  - application/json
securityDefinitions:
  bearerAuth:
    type: apiKey
    in: header
    name: Authorization
security:
  - bearerAuth: []
paths:
  /users:
    post:
      summary: Create a user
      parameters:
        - in: body
          name: body
          required: true
          schema:
            $ref: "#/definitions/NewUser"
      responses:
        "201":
          description: User created
          schema:
            $ref: "#/definitions/User"
        "400":
          description: Invalid input
  /users/{id}:
    get:
      summary: Get a user
      parameters:
        - name: id
          in: path
          required: true
          type: string
      responses:
        "200":
          description: The user
          schema:
            $ref: "#/definitions/User"
        "404":
          description: User not found
definitions:
  NewUser:
    type: object
    required: [email]
    properties:
      email:
        type: string
        format: email
      nickname:
        type: string
        x-nullable: true
  User:
    type: object
    required: [id, email]
    properties:
      id:
        type: string
      email:
        type: string
        format: email
      nickname:
        type: string
        x-nullable: true
Swagger 2.0. Note the body parameter, definitions, and the apiKey workaround for a bearer token.
YAMLusers.openapi30.yaml
openapi: 3.0.3
info:
  title: Users API
  version: 1.0.0
servers:
  - url: https://api.example.com/v1
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
  schemas:
    NewUser:
      type: object
      required: [email]
      properties:
        email:
          type: string
          format: email
        nickname:
          type: string
          nullable: true
    User:
      type: object
      required: [id, email]
      properties:
        id:
          type: string
        email:
          type: string
          format: email
        nickname:
          type: string
          nullable: true
security:
  - bearerAuth: []
paths:
  /users:
    post:
      summary: Create a user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/NewUser"
      responses:
        "201":
          description: User created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "400":
          description: Invalid input
  /users/{id}:
    get:
      summary: Get a user
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: The user
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "404":
          description: User not found
The same API in OpenAPI 3.0.3.

Line by line, these are the changes. Every row is a direct consequence of the 2.0 and 3.0 specifications:

ConcernSwagger 2.0OpenAPI 3.0
Version fieldswagger: "2.0"openapi: 3.0.3
Base URLhost, basePath and schemes, one host onlyservers list of URLs, with optional {variables}
Request bodyA parameter with in: body (at most one per operation)requestBody with content keyed by media type
Form fields and uploadsin: formData parameters, type: filerequestBody with multipart/form-data or application/x-www-form-urlencoded
Media typesconsumes and produces lists at root or operation levelMedia type keys inside each requestBody and response content
Reusable schemasdefinitionscomponents/schemas
Other reusable partsparameters, responses at the rootcomponents holds schemas, responses, parameters, examples, requestBodies, headers, securitySchemes, links and callbacks
Security schemessecurityDefinitions with basic, apiKey or oauth2components/securitySchemes with apiKey, http (basic, bearer and others), oauth2 or openIdConnect
Null valuesNo nullable keyword; tools use the x-nullable extensionnullable: true on the schema
Response bodyschema directly on the responseschema under content and a media type
Callbacks and linksNot availablecallbacks for out-of-band requests, links between operations
Swagger 2.0 compared with OpenAPI 3.0.

Two rows change what the file says about the API. Swagger 2.0 has no bearer scheme, so the 2.0 file describes the token as an apiKey in the Authorization header. That works, but generated clients will not add the Bearer prefix for you; in 3.0, type: http with scheme: bearer says exactly what the server expects. And because 2.0 keeps media types in consumes and produces lists, one operation cannot give JSON and XML responses different schemas. OpenAPI 3.0 puts a schema under each media type.

What changed from OpenAPI 3.0 to 3.1

OpenAPI 3.1 keeps the 3.0 structure and changes the schema language. In 3.0, the Schema Object is an extended subset of JSON Schema: type must be a single string, and nullable: true stands in for null. In 3.1, schemas follow JSON Schema draft 2020-12, so any JSON Schema validator for that draft can read them. The OpenAPI Initiative's upgrade guide lists the edits most files need:

  • Replace nullable: true with a type array: type: [string, "null"].
  • Change exclusiveMinimum: true next to minimum: 7 into exclusiveMinimum: 7. The keyword now takes the number itself.
  • Replace example on a schema with examples, which takes an array.
  • Describe binary uploads with contentMediaType or an empty schema instead of format: binary, and base64 data with contentEncoding: base64.
  • Change the version field to openapi: 3.1.0 or 3.1.1.

For every change with before and after YAML, see OpenAPI 3.0 vs 3.1. To move a Swagger 2.0 file forward first, follow how to convert Swagger 2.0 to OpenAPI 3.

3.1 also adds fields. webhooks is a new top-level object for requests your API sends to subscribers. paths is no longer required: a document needs openapi and info, plus at least one of paths, components or webhooks, which allows a file that holds only shared schemas. components gains pathItems, info gains summary, license gains an SPDX identifier, and security schemes gain mutualTLS. The User schema below shows the 3.1 versions of the fields from the earlier example.

YAMLusers.openapi31.yaml
openapi: 3.1.0
info:
  title: Users API
  version: 1.0.0
  summary: Create and read user accounts.
  license:
    name: MIT
    identifier: MIT
components:
  schemas:
    User:
      type: object
      required: [id, email]
      properties:
        id:
          type: string
        email:
          type: string
          format: email
        nickname:
          type: [string, "null"]
          examples: [dana]
        age:
          type: integer
          exclusiveMinimum: 0
webhooks:
  userDeleted:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/User"
      responses:
        "200":
          description: Webhook received
OpenAPI 3.1: type arrays for null, examples as a list, numeric exclusiveMinimum, and a top-level webhook.

What the version does not change

The design of the API is the same in every version. We scored both the Swagger 2.0 and the OpenAPI 3.0 file above with the APIForge quality score, and both got 91 out of 100 with the same single issue: no version segment in the paths. The /v1 is there, but in basePath for 2.0 and in the server URL for 3.0, and the score reads the path keys. Whether that matters is your call; versioning in the base URL is a legitimate choice. It shows that converting a file to a newer format does not fix naming, missing error responses or anything else about the API itself.

Which version should you write?

Choosing a spec version

ScenarioRecommendationAlternative
You are starting a new APIWrite OpenAPI 3.1 if your generator, gateway and docs tools read it.Use 3.0.3 if any tool in your pipeline only reads 3.0. Converting 3.0 to 3.1 later is a short list of edits.
You have a working Swagger 2.0 file and no tool needs 3.xLeave it until you need a 3.x feature such as a bearer scheme, oneOf or several media types.—
You need webhooks, null in enum lists, or plain JSON Schema validatorsUse 3.1. These are the cases where 3.0's schema subset gets in the way.—
Your framework generates the spec from codeUse the version it emits and check that setting when you upgrade the framework.—

Converting Swagger 2.0 to OpenAPI 3

Converters such as the swagger2openapi npm package handle the mechanical part: host and basePath become servers, definitions move to components/schemas, body parameters become requestBody, and $ref pointers are rewritten. Review these by hand afterwards, because a converter cannot know your intent:

After an automatic conversion

  1. Fix the security scheme

    An apiKey on the Authorization header usually means a bearer token. Replace it with type: http and scheme: bearer.

  2. Replace vendor extensions

    x-nullable: true becomes nullable: true in 3.0, or a type array in 3.1. Search the file for other x- keys your old tooling relied on.

  3. Check form and file parameters

    formData parameters and type: file need a multipart/form-data or application/x-www-form-urlencoded requestBody. Confirm each field's encoding.

  4. Split shared media types

    If the 2.0 file listed several produces types, the converter copies one schema to each. Split them if JSON and XML bodies differ.

  5. Validate and compare

    Validate the new file, then load both versions and compare operation counts and parameters, so nothing was dropped.

The spec validation guide covers adding that validation step to CI so a broken conversion never merges.

Open either version in APIForge

APIForge reads Swagger 2.0, OpenAPI 3.0 and OpenAPI 3.1. Paste a file or URL into the Swagger 2.0 validator or the OpenAPI validator and it parses the document, resolves references, builds request URLs from host, basePath and schemes for 2.0 files or from servers for 3.x, and treats 2.0 body parameters as the request body. It does not export a converted file, so use a converter for that step and APIForge to check that the result still lists the same operations.

Frequently asked questions

Swagger 2.0 and OpenAPI 2.0 are the same specification under two names. From 3.0 on, the format is only called OpenAPI, and Swagger refers to SmartBear's tools such as Swagger UI and Swagger Editor.

Yes. A Swagger 2.0 file is still a valid OpenAPI 2.0 document, and many tools read it. It lacks 3.x features such as requestBody, a bearer security scheme, oneOf and per-media-type schemas, so new APIs usually start on 3.0 or 3.1.

Read the first field. swagger: "2.0" means Swagger or OpenAPI 2.0, and openapi: 3.0.x or 3.1.x means OpenAPI 3. The file name, such as swagger.json, does not tell you the version.

Yes. APIForge parses Swagger 2.0, OpenAPI 3.0 and OpenAPI 3.1 documents from a URL or a file. It does not convert between versions, so use a converter such as swagger2openapi for that.

Sources

  1. OpenAPI Specification FAQ (history of the Swagger donation)OpenAPI Initiative
  2. OpenAPI Specification 2.0 (fka Swagger RESTful API Documentation Specification)OpenAPI Initiative
  3. OpenAPI Specification 3.0.3OpenAPI Initiative
  4. OpenAPI Specification 3.1.0OpenAPI Initiative
  5. Upgrading from OpenAPI 3.0 to 3.1OpenAPI Initiative
  6. Swagger 2.0 basic structureSwagger documentation