Spectral.OpenAPI (Spectral v0.9.2)

View Source

Elixir wrapper for spectra OpenAPI specification generation.

This module provides idiomatic Elixir functions for generating OpenAPI 3.1 specifications from Elixir type definitions using spectra.

Response Builder Pattern

Responses are built using a fluent API:

response = Spectral.OpenAPI.response(200, "Success")
  |> Spectral.OpenAPI.response_with_body(Person, :t)
  |> Spectral.OpenAPI.response_with_header("X-Rate-Limit", RateLimit, :t, %{
    description: "Remaining requests",
    required: false
  })

endpoint = Spectral.OpenAPI.endpoint(:get, "/users/{id}")
  |> Spectral.OpenAPI.add_response(response)

Summary

Functions

Adds a complete response specification to an endpoint.

Creates a new OpenAPI endpoint definition.

Creates a new OpenAPI endpoint definition using metadata from a spectral/1 macro placed before a function definition.

Converts a list of endpoints to a complete OpenAPI specification.

Converts a list of endpoints to a complete OpenAPI specification, with options.

Creates a response builder.

Adds a response body to a response builder.

Adds a response body with custom content type to a response builder.

Adds a parameter to an endpoint.

Adds a request body specification to an endpoint.

Adds a request body specification with a custom content type to an endpoint.

Functions

add_response(endpoint, response)

Adds a complete response specification to an endpoint.

This function adds a response that was built using the response builder pattern.

Parameters

  • endpoint - The endpoint to add the response to
  • response - Response specification built with response/2 and related functions

Returns

  • endpoint - Updated endpoint with the response added

Example

response = Spectral.OpenAPI.response(200, "User found")
  |> Spectral.OpenAPI.response_with_body(Person, :t)

endpoint = Spectral.OpenAPI.endpoint(:get, "/users/{id}")
  |> Spectral.OpenAPI.add_response(response)

endpoint(method, path, doc \\ %{})

Creates a new OpenAPI endpoint definition.

Parameters

  • method - HTTP method as an atom (:get, :post, :put, :delete, :patch, etc.)
  • path - URL path as a binary (e.g., "/users/{id}")
  • doc - Optional documentation map with optional keys:
    • :summary - Short summary of the endpoint
    • :description - Longer description of the endpoint
    • :operationId - Unique string to identify the operation
    • :tags - List of tags for grouping endpoints
    • :deprecated - Whether the endpoint is deprecated (boolean)
    • :externalDocs - Map with :url (required) and :description (optional)

Returns

  • endpoint - OpenAPI endpoint structure

Example

iex> endpoint = Spectral.OpenAPI.endpoint(:get, "/users/{id}", %{summary: "Get user by ID"})
iex> endpoint.doc
%{summary: "Get user by ID"}

endpoint(method, path, module, function_name, arity)

Creates a new OpenAPI endpoint definition using metadata from a spectral/1 macro placed before a function definition.

The function's metadata (set via spectral summary: "...", description: "..." before the corresponding @spec) is retrieved from the module's type info and used as the endpoint documentation.

Parameters

  • method - HTTP method as an atom (:get, :post, :put, :delete, :patch, etc.)
  • path - URL path as a binary (e.g., "/users/{id}")
  • module - The module containing the function with spectral metadata
  • function_name - The function name as an atom
  • arity - The function arity

Returns

  • endpoint - OpenAPI endpoint structure with documentation from the function's metadata

Example

defmodule MyController do
  use Spectral

  spectral summary: "Get user", description: "Returns a user by ID"
  @spec get_user(map(), map()) :: map()
  def get_user(_conn, _params), do: %{}
end

endpoint = Spectral.OpenAPI.endpoint(:get, "/users/{id}", MyController, :get_user, 2)

endpoints_to_openapi(metadata, endpoints)

@spec endpoints_to_openapi(
  :spectra_openapi.openapi_metadata(),
  [:spectra_openapi.endpoint_spec()]
) :: {:ok, iodata()} | {:error, [Spectral.Error.t()]}

Converts a list of endpoints to a complete OpenAPI specification.

Parameters

  • metadata - OpenAPI metadata map with keys:
    • :title - API title (required)
    • :version - API version (required)
    • :summary (optional) - Short summary of the API
    • :description (optional) - Longer description of the API
    • :terms_of_service (optional) - URL to the terms of service
    • :contact (optional) - Contact map with optional :name, :url, :email
    • :license (optional) - License map with required :name and optional :url, :identifier
    • :servers (optional) - List of server objects, each with required :url and optional :description
  • endpoints - List of endpoint definitions

Returns

  • {:ok, iodata} - Complete OpenAPI 3.1 specification serialised as JSON iodata
  • {:error, [%Spectral.Error{}]} - List of errors if generation fails

Example

metadata = %{title: "My API", version: "1.0.0"}
endpoints = [
  Spectral.OpenAPI.endpoint(:get, "/users/{id}")
  |> Spectral.OpenAPI.add_response(
    Spectral.OpenAPI.response(200, "User found")
    |> Spectral.OpenAPI.response_with_body(Person, :t)
  )
]

{:ok, json} = Spectral.OpenAPI.endpoints_to_openapi(metadata, endpoints)

endpoints_to_openapi(metadata, endpoints, opts)

@spec endpoints_to_openapi(
  :spectra_openapi.openapi_metadata(),
  [:spectra_openapi.endpoint_spec()],
  [
    Spectral.schema_option()
  ]
) :: {:ok, iodata() | dynamic()} | {:error, [Spectral.Error.t()]}

Converts a list of endpoints to a complete OpenAPI specification, with options.

Like endpoints_to_openapi/2 but accepts an options list.

Parameters

  • metadata - OpenAPI metadata map (same as endpoints_to_openapi/2)
  • endpoints - List of endpoint definitions
  • opts - Options list. Supported options:
    • :pre_encoded - Return a map instead of iodata, skipping JSON encoding.

Returns

  • {:ok, iodata()} - Complete OpenAPI 3.1 spec as JSON iodata (default)
  • {:ok, map()} - Spec as a decoded map when :pre_encoded option is set
  • {:error, [%Spectral.Error{}]} - List of errors if generation fails

response(status_code, description)

Creates a response builder.

This creates a response specification that can be further configured with response_with_body/3-4 and response_with_header/4 before being added to an endpoint with add_response/2.

Parameters

  • status_code - HTTP status code (e.g., 200, 404, 500)
  • description - Human-readable description of the response

Returns

  • response - Response builder structure

Example

response = Spectral.OpenAPI.response(200, "User found successfully")

response_with_body(response, module, schema)

Adds a response body to a response builder.

Parameters

  • response - Response builder from response/2
  • module - Module containing the type definition
  • schema - Schema reference (typically an atom like :t)

Returns

  • response - Updated response builder with body schema

Example

response = Spectral.OpenAPI.response(200, "Success")
  |> Spectral.OpenAPI.response_with_body(Person, :t)

response_with_body(response, module, schema, content_type)

Adds a response body with custom content type to a response builder.

Parameters

  • response - Response builder from response/2
  • module - Module containing the type definition
  • schema - Schema reference (typically an atom like :t)
  • content_type - Content type (e.g., "application/json", "application/xml")

Returns

  • response - Updated response builder with body schema and content type

Example

response = Spectral.OpenAPI.response(200, "Success")
  |> Spectral.OpenAPI.response_with_body(Person, :t, "application/xml")

response_with_header(response, header_name, module, header_spec)

@spec response_with_header(
  :spectra_openapi.response_spec(),
  binary(),
  module(),
  map()
) ::
  :spectra_openapi.response_spec()

Adds a header to a response builder.

Parameters

  • response - Response builder from response/2
  • header_name - Name of the response header (e.g., "X-Rate-Limit")
  • module - Module containing the type definition for the header value
  • header_spec - Header specification map with keys:
    • :description (optional) - Description of the header
    • :required (optional) - Whether the header is required (default: false)
    • :deprecated (optional) - Whether the header is deprecated (boolean)
    • :schema - Schema for the header value

Returns

  • response - Updated response builder with header added

Example

response = Spectral.OpenAPI.response(200, "Success")
  |> Spectral.OpenAPI.response_with_header("X-Rate-Limit", RateLimit, :t, %{
    description: "Requests remaining",
    required: false,
    schema: :integer
  })

with_parameter(endpoint, module, parameter_spec)

Adds a parameter to an endpoint.

Parameters can be in the path, query string, headers, or cookies.

Parameters

  • endpoint - The endpoint to modify
  • module - Module containing the type definition for the parameter
  • parameter_spec - Parameter specification map with keys:
    • :name - Parameter name
    • :in - Location (:path, :query, :header, :cookie)
    • :required - Whether the parameter is required
    • :schema - Schema for the parameter value (atom or {:type, name, arity} tuple)

The description and deprecated fields in the rendered OpenAPI output are sourced from the type's spectral annotation, not from the parameter spec. Type aliases and remote type references are followed automatically to inherit their documentation.

Returns

  • endpoint - Modified endpoint with parameter added

Example

endpoint = Spectral.OpenAPI.endpoint(:get, "/users/{id}")
  |> Spectral.OpenAPI.with_parameter(User, %{
    name: "id",
    in: :path,
    required: true,
    schema: :string
  })

with_request_body(endpoint, module, schema)

Adds a request body specification to an endpoint.

Parameters

  • endpoint - The endpoint to modify
  • module - Module containing type definitions
  • schema - Schema reference (typically an atom like :t)

Returns

  • endpoint - Modified endpoint with request body

Example

endpoint = Spectral.OpenAPI.endpoint(:post, "/users")
  |> Spectral.OpenAPI.with_request_body(Person, :t)

with_request_body(endpoint, module, schema, content_type)

Adds a request body specification with a custom content type to an endpoint.

Parameters

  • endpoint - The endpoint to modify
  • module - Module containing type definitions
  • schema - Schema reference (typically an atom like :t)
  • content_type - Content type binary (e.g., "application/xml"; defaults to "application/json")

Returns

  • endpoint - Modified endpoint with request body

Example

endpoint = Spectral.OpenAPI.endpoint(:post, "/users")
  |> Spectral.OpenAPI.with_request_body(Person, :t, "application/xml")