What is OpenAPI? Introduction to OpenAPI Specification (OAS)

OpenAPI continues to evolve and sustain a vibrant, interconnected API economy. Here, we define what exactly OpenAPI is, how OpenAPI definitions are structured, explore a real-world OAS example, and look at how OpenAPI is becoming the foundation for AI agent interactions with APIs.

GJGJ

GJ

30 min read
What is OpenAPI? Introduction to OpenAPI Specification (OAS)

OpenAPI Specification (OAS) has become the standard way to define HTTP APIs. Like a universal adapter, an OpenAPI definition describes API methods and metadata, increasing API knowledge and portability across environments. Commonly used in auto-documentation, code generation, and design-first development, OpenAPI's pivotal role across many areas of the API economy cannot be overstated.

What-is-OpenAPI--Introduction-to-OpenAPI-Specification-(OAS)

The offspring of Swagger, OpenAPI is now a vendor-neutral standard supported by the OpenAPI Initiative, a Linux Foundation project. With this strong backing, OpenAPI continues to evolve and sustain a vibrant, interconnected API economy. Below, we'll define what exactly OpenAPI is, how OpenAPI definitions are structured, explore a real-world spec example, and look at how OpenAPI is becoming the foundation for AI agent interactions with APIs.

What is OpenAPI?

OpenAPI is a standard way to describe HTTP-based APIs. Formerly known as Swagger, SmartBear donated OpenAPI in 2015 with the formation of the OpenAPI Initiative (OAI), an industry consortium governed by about 40 participating members representing some major tech interests.

So, what does OpenAPI accomplish? Think of OpenAPI as a lingua franca for everything API. Building off a common spec enables collaborative, design-first development practices. If you are iteratively improving your APIs, utilizing an API schema as a source of truth is vital to conform to API style and governance policies. With this source of truth, engineers can also auto-generate valuable materials, such as documentation, SDKs, code libraries, and more, thus reducing development effort. In fact, many tools exist to help developers leverage the power of OpenAPI to enable conversion, validation, linting, and other capabilities.

The OpenAPI Specification does not mandate a specific development process such as design-first or code-first. To understand OpenAPI, it helps to clarify three terminologies that are often conflated β€” specification, definition, and documentation:

  • OpenAPI Specification (OAS): The industry-standard specification that outlines how OpenAPI files are structured, outlined here.
  • OpenAPI Description: Your actual API description file that represents your specific API use case. This schema is machine-readable and represented in either YAML or JSON. (Note: The OAI now prefers the term "OpenAPI Description" over "definition" for consistency.)
  • API Documentation: The visual, human-readable representation of the API structure. Applies HTML, CSS, and JavaScript to enable API navigation and discovery.

In short, OpenAPI makes APIs more shareable, extensible, reusable, and consistent for both internal and external stakeholders. So, what does it look like?

OpenAPI definition structure

A basic OpenAPI definition is structured around a few key sections:

OpenAPI-visual-structure-v3

The info field contains high-level information about the API, such as version, title, and license. The servers field denotes the root endpoints for the API. For example:

openapi: "3.1.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  summary: A sample pet store API
  license:
    name: MIT
    identifier: MIT
servers:
  - url: http://petstore.swagger.io/v1

Next, an OpenAPI file outlines the paths for the API. These describe the specific methods that can be reached, as well as their parameters, responses, human-readable descriptions of functionality, accepted content types, tags, and other expected behaviors. For example, here is a get call to the /pets path:

paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            maximum: 100
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

An OpenAPI description would likely define many more paths, as well as additional HTTP method operations for the same path, such as post, put, or delete.

Another useful object is the components object, which holds a set of reusable objects for different OAS elements to reference throughout the spec:

components:
  schemas:
    Pet:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string

A real-world OAS example: Invoice API

The petstore example above is useful for learning, but let's look at something closer to what you'd encounter in production. Here's a partial OpenAPI 3.1.0 spec for an accounting API that manages invoices β€” the kind of thing you'd see in fintech, vertical SaaS, or embedded finance:

openapi: 3.1.0
info:
  title: Invoice API
  version: 1.0.0
  description: >
    A unified API for managing invoices across multiple accounting platforms.
    Supports creating, listing, and retrieving invoices with line items.
  contact:
    name: API Support
    email: support@example.com

servers:
  - url: https://api.example.com/v1
    description: Production
  - url: https://sandbox.example.com/v1
    description: Sandbox

security:
  - apiKey: []

paths:
  /invoices:
    get:
      operationId: listInvoices
      summary: List all invoices
      description: Returns a paginated list of invoices, sorted by creation date.
      tags:
        - Invoices
      parameters:
        - name: cursor
          in: query
          description: Pagination cursor from a previous response.
          schema:
            type: string
        - name: limit
          in: query
          description: Number of results to return. Max 200.
          schema:
            type: integer
            default: 20
            maximum: 200
        - name: status
          in: query
          description: Filter invoices by status.
          schema:
            type: string
            enum:
              - draft
              - sent
              - paid
              - overdue
              - void
      responses:
        '200':
          description: A list of invoices.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Invoice'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthorized'

    post:
      operationId: createInvoice
      summary: Create an invoice
      description: Creates a new invoice in draft status.
      tags:
        - Invoices
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InvoiceInput'
      responses:
        '201':
          description: Invoice created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Invoice'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'

  /invoices/{id}:
    get:
      operationId: getInvoice
      summary: Get an invoice
      description: Retrieves a single invoice by its ID.
      tags:
        - Invoices
      parameters:
        - name: id
          in: path
          required: true
          description: The unique identifier of the invoice.
          schema:
            type: string
      responses:
        '200':
          description: An invoice object.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Invoice'
        '404':
          $ref: '#/components/responses/NotFound'

components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key

  schemas:
    Invoice:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the invoice.
          example: "inv_01H8XKZQ3ABCDEF"
        number:
          type: string
          description: Human-readable invoice number.
          example: "INV-2025-0042"
        status:
          type: string
          enum: [draft, sent, paid, overdue, void]
          example: "sent"
        customer:
          type: object
          properties:
            id:
              type: string
              example: "cus_01H8XKZQ3GHIJKL"
            name:
              type: string
              example: "Acme Corp"
            email:
              type: string
              format: email
              example: "billing@acme.com"
        currency:
          type: string
          description: ISO 4217 currency code.
          example: "USD"
        line_items:
          type: array
          items:
            $ref: '#/components/schemas/LineItem'
        total:
          type: number
          format: double
          description: Total amount due including tax.
          example: 1815.00
        due_date:
          type: string
          format: date
          example: "2025-04-15"
        created_at:
          type: string
          format: date-time
          example: "2025-03-01T10:30:00Z"

    LineItem:
      type: object
      properties:
        description:
          type: string
          example: "Software development services - March 2025"
        quantity:
          type: number
          example: 40
        unit_price:
          type: number
          format: double
          example: 37.50
        amount:
          type: number
          format: double
          description: quantity Γ— unit_price
          example: 1500.00
        tax_rate:
          type: number
          format: double
          description: Tax rate as a decimal (e.g., 0.21 for 21%).
          example: 0.21

    InvoiceInput:
      type: object
      required:
        - customer_id
        - currency
        - line_items
      properties:
        customer_id:
          type: string
          description: The ID of the customer to invoice.
        currency:
          type: string
          description: ISO 4217 currency code.
        due_date:
          type: string
          format: date
          description: Payment due date. Defaults to 30 days from creation.
        line_items:
          type: array
          minItems: 1
          items:
            type: object
            required:
              - description
              - quantity
              - unit_price
            properties:
              description:
                type: string
              quantity:
                type: number
              unit_price:
                type: number
                format: double
              tax_rate:
                type: number
                format: double

    PaginationMeta:
      type: object
      properties:
        cursor:
          type: ["string", "null"]
          description: Cursor for the next page. Null if no more results.
        has_more:
          type: boolean

    Error:
      type: object
      properties:
        status_code:
          type: integer
        error:
          type: string
        message:
          type: string

  responses:
    Unauthorized:
      description: Authentication failed or API key is missing.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: The requested resource was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    UnprocessableEntity:
      description: The request body was well-formed but contains semantic errors.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

A few things worth calling out in this spec:

  • Reusable components. Schemas like Invoice, LineItem, and Error are defined once under components/schemas and referenced with $ref everywhere else. Same with error responses. This keeps your spec DRY and maintainable.
  • Cursor-based pagination. Instead of page numbers, we use an opaque cursor. This is more reliable for APIs where data changes frequently. The PaginationMeta schema makes pagination behavior explicit.
  • Clear operation IDs. Every operation has an operationId like listInvoices or createInvoice. These IDs are what SDK generators use as method names. Get them right and your generated SDKs will have clean, predictable interfaces.
  • Enums for status fields. Defining status as an enum (draft, sent, paid, overdue, void) means consumers know exactly what values to expect.
  • Nullable values using JSON Schema syntax. Notice type: ["string", "null"] on the cursor field β€” this is the 3.1+ way to handle nullable types, replacing the old nullable: true from 3.0.
  • Examples on every field. Adding example values means tools like Swagger UI can render realistic mock data, and AI agents can understand what valid data looks like.

OpenAPI version history

OpenAPI 3.0 (2017)

The jump from 2.0 (Swagger) to 3.0 was a major structural overhaul. It introduced components for reusable schemas, servers replacing host/basePath, support for multiple content types per response, and callbacks for describing asynchronous behavior. Most of the modern tooling ecosystem was built around 3.0.

OpenAPI 3.1 (2021)

The most important change in 3.1: full JSON Schema compatibility. In 3.0, OpenAPI used an "extended subset" of JSON Schema that had quirks and limitations. In 3.1, your schemas are real JSON Schema (Draft 2020-12), which means you get if/then/else, prefixItems, $dynamicRef, and everything else JSON Schema supports.

Other notable changes:

  • nullable: true is replaced by type: ["string", "null"] (standard JSON Schema)
  • Webhooks get first-class support via a top-level webhooks key
  • summary added to the info object
  • Licenses can use SPDX identifiers
  • PathItems become optional, enabling reusable component libraries

OpenAPI 3.2 (September 2025)

The latest feature release. OpenAPI 3.2 is backwards compatible with 3.1 β€” your existing descriptions keep working β€” but it introduces several meaningful capabilities:

Hierarchical tags. Tags are no longer a flat list. The new summary, parent, and kind fields let you build nested navigation structures directly in the spec. If you've been relying on vendor extensions like x-tagGroups for documentation, this replaces them with a standard approach:

tags:
  - name: accounting
    summary: Accounting operations
    kind: nav
  - name: accounting.invoices
    summary: Invoice management
    parent: accounting
    kind: nav

Streaming support. OpenAPI 3.2 formally recognizes streaming media types like text/event-stream, application/jsonl, and application/x-ndjson as first-class citizens. The new itemSchema keyword defines what individual streamed events look like. This is critical for AI, IoT, and financial services use cases where streaming is standard.

QUERY HTTP method. A new method for safely querying resource state with a request body, without abusing POST. You can also define custom HTTP methods via the new additionalOperations keyword.

OAuth 2.0 Device Authorization Flow. Support for device-based auth flows (smart TVs, kiosks, CLI tools) is now built into the security scheme definitions.

Improved examples. New dataValue and serializedValue properties let you specify both the logical and wire-format representations of example data.

If you're starting a new API today, 3.2 is the version to use. If you're already on 3.1, the upgrade path is gentle β€” adopt features incrementally.

The OpenAPI ecosystem: companion specifications

OpenAPI doesn't stand alone anymore. The OpenAPI Initiative now maintains three complementary specifications:

Arazzo

Arazzo is a specification for orchestrating multi-step API workflows. Where OpenAPI describes individual endpoints, Arazzo describes sequences of API calls β€” each step referencing an existing OpenAPI document, with success criteria that determine whether the next step executes. This is valuable for interactive documentation (walking users through multi-step flows), SDK generation (multi-call functions), and testing realistic API workflows. Arazzo v1.1.0 is in progress, with AsyncAPI support planned.

Overlay

Overlay provides a standardized way to apply transformations to an OpenAPI description without modifying the original. This is critical when you need to inject different SDK examples, generate different flavors of specs for different tooling, or augment API descriptions with additional context β€” all without touching the upstream spec.

Helpful OpenAPI tools

A clear benefit to adopting OpenAPI is leveraging the expansive tooling ecosystem around it. OpenAPI.tools is a comprehensive resource. Here are the most popular tools across key areas:

OpenAPI in the agentic era

OpenAPI specs are no longer just for human developers and code generators. They're becoming the primary way AI agents discover and interact with APIs.

When an AI coding agent like Claude Code, Cursor, or Windsurf needs to integrate with your API, the first thing it looks for is a machine-readable description. If your OpenAPI spec is well-structured β€” with clear descriptions, good examples, and explicit error handling β€” an AI agent can generate a working integration in seconds.

The same applies to MCP (Model Context Protocol) servers, LLM function calling, and tool-use frameworks. All of these rely on structured API descriptions to understand what tools are available and how to use them. In fact, OpenAPI 3.2's streaming support was explicitly designed with AI use cases in mind β€” describing SSE streams and JSON Lines formats that power LLM token streaming.

As we wrote in our piece on API design principles for the agentic era, the right sequence for most API companies is: get your OpenAPI spec right, write real descriptions, add documentation_url to your errors, publish /llms.txt, get indexed by discovery tools. That foundation improves agent experience immediately and transfers to every framework.

A few things that make your OpenAPI spec more AI-friendly:

  • Descriptive operationId values. listInvoices is better than get_v1_invoices_list. These become the function names AI agents use.
  • Rich descriptions on every field. AI agents use these to understand context and make decisions about which endpoint to call and what parameters to pass.
  • Realistic examples. Helps agents construct valid requests without guessing.
  • Clear error schemas. Agents need to understand failure modes to handle them gracefully. Include a documentation_url in error responses so agents can self-serve recovery.
  • Explicit security schemes. So agents know what authentication is required before making a call.

The OpenAPI Initiative is actively moving in this direction. OpenAPI 3.3 is planned to include greater integration with MCP and AI protocols, and the community has called for an official OpenAPI registry β€” comparable to the MCP server registry β€” where developers and AI agents can discover and access specifications.

Examples of OpenAPI in production

SDK auto-generation at Xero

Xero, one of the world's largest accounting platforms, auto-generates SDKs from its OpenAPI files using OpenAPI Generator. This pattern has been adopted widely β€” Square, Stripe, and many others use the same approach to maintain client libraries across multiple languages with minimal manual effort.

import-api-xero-case-study

Discourse generates API docs using Redocly

Discourse uses their OpenAPI definition with Redocly to auto-generate public API documentation. The three-column layout makes it easy to explore methods, read implementation instructions, and view sample requests and responses.

Discourse API Documentation

Postman and OpenAPI

Postman allows developers to import, validate, and test OpenAPI definitions directly. With OpenAPI support, Postman enables validating and syncing during development, validating API responses, and helps developers better organize their Collections by utilizing OpenAPI tags.

Postman API schema

How we use OpenAPI at Apideck

At Apideck, OpenAPI is foundational to everything we build. Every one of our 200+ unified API connectors is built on this specification. It's the common language that allows us to normalize disparate APIs from accounting, HRIS, CRM, and other categories into consistent, predictable interfaces. Without OpenAPI, Apideck simply wouldn't exist in its current form.

We use OpenAPI to power our documentation, generate SDKs across six programming languages, run automated contract tests via Portman, and maintain a transparent, spec-driven development process. Our OpenAPI specs are open source on GitHub, and we receive design feedback directly on the repository.

In 2025, we became the first unified API company to join the OpenAPI Initiative. Beyond the foundational OpenAPI Specification, we're helping shape emerging standards like Arazzo (for orchestrating multi-API workflows) and Overlay (for programmatically managing spec transformations across our 200+ connectors). We're also contributing our perspective on what an official OpenAPI registry could look like β€” because the API ecosystem needs a centralized, authoritative place where developers and AI agents can discover specifications.

apideck openapi repository

OpenAPI benefits

OpenAPI can streamline internal API development considerably. Coalescing around a common specification helps direct collaborative, definition-driven API development, translating into more efficient projects and more targeted rollouts. By conforming to OpenAPI, organizations can also reproduce consistent API style, increasing the reusability of internal offerings and powering new innovations in a standardized way.

Next, consider the impact on developer experience. With beautiful documentation, developers can easily explore an API, improving the learning process while reducing the effort to maintain a developer portal. Utilizing OpenAPI tooling to produce additional resources β€” code samples, SDKs, and libraries β€” can tremendously improve the developer experience while allowing you to cast a wider net across programming languages.

And increasingly, OpenAPI improves the agent experience. As AI coding agents and LLM-powered tools become the primary consumers of API documentation, a well-structured OpenAPI spec is what separates APIs that get recommended by AI agents from APIs that get ignored. Investing in your spec is investing in your API's discoverability.

Lastly, adopting OpenAPI means supporting the overall API ecosystem. No other API specification has reached its level of standardization. It's a Linux Foundation project with top tech company backing, three companion specifications (Arazzo, Overlay, and the core OAS), and a roadmap that's actively incorporating AI-native use cases. This translates into stability for the spec and stability for the surrounding adopters and integrators.

Conclusion: You probably need an OpenAPI description

For years, the API industry searched for a specification to represent commonalities among thousands of APIs. Today, OpenAPI dominates the market β€” though to be fair, it's one of many options. AsyncAPI, JSON Schema, RAML, GraphQL, and gRPC provide other ways to describe and document APIs.

Nevertheless, OpenAPI has found an intrinsic home within the majority of modern API developer toolkits. By standardizing how HTTP APIs are defined, OpenAPI enhances internal reusability and external consumption. With backing from tech giants like Google, IBM, Microsoft, and SAP β€” and with AI agents increasingly relying on structured API descriptions β€” it seems OpenAPI is more essential than ever.

If you don't already have an OpenAPI description for your API program, there's never been a better time to start. And if you have one that's gathering dust, dust it off β€” the AI agents are looking for it.

Next up: Ready to turn your spec into a test suite? Read our complete guide to OpenAPI testing covering contract tests, fuzz testing, variation tests, and how to build a CI/CD pipeline with tools like Portman, Schemathesis, and Inspectr.

Ready to get started?

Scale your integration strategy and deliver the integrations your customers need in record time.

Ready to get started?
Talk to an expert

Trusted by fast-moving product & engineering teams

JobNimbus
Blue Zinc
Drata
Octa
Nmbrs
Apideck Blog

Insights, guides, and updates from Apideck

Discover company news, API insights, and expert blog posts. Explore practical integration guides and tech articles to make the most of Apideck's platform.