OpenAPI

REST Framework auto-generates an OpenAPI document for every controller, reflecting the real configuration that drives the API: fields, field_config, validators, enum variants, association metadata, rich-text and attachment fields, bulk support, and more. The document is served from the controller’s OPTIONS endpoint — no extra setup, no drift between spec and behavior.

Fetching the Document

Every REST Framework controller responds to OPTIONS with its OpenAPI document:

curl -X OPTIONS https://example.com/api/movies

From a browser, the OPTIONS action also has an HTML rendering accessible from the route list in the browsable API, so you can explore the document interactively.

Customizing the Document

The fields of the info block and the tag description come from standard controller attributes:

class Api::MoviesController < ApiController
  self.model = Movie
  self.title = "Movies API"
  self.description = "Read and manage movie records. Supports bulk operations."
  self.version = "2026.04"
end

If title is unset, it falls back to the controller’s titleized class name, with RESTFramework.config.inflect_acronyms applied so things like "ID", "API", and "REST" stay capitalized.

Schema Generation

When the controller has a model, the OpenAPI document includes a full schema for that model under components.schemas.<SchemaName>. The schema name defaults to the controller class name with "Controller" stripped and "::" replaced with "." — so Api::MoviesController becomes Api.Movies. Every field becomes a property:

On top of the standard OpenAPI vocabulary, the framework adds several x-rrf-* extensions for browsable-API clients and tools that want to consume the full field metadata.

x-rrf-* Extensions

Schema-level (per field)

Extension Description
x-rrf-kind "column", "association", "method", "attribute", "rich_text", or "attachment".
x-rrf-rich_text true when the field is an Action Text rich text attribute.
x-rrf-attachment :has_one_attached or :has_many_attached for Active Storage attachments.
x-rrf-enum_variants Full map of enum name → database value (standard enum only lists keys).
x-rrf-validators Hash of validator kind → array of option hashes, for every model-level validator.
x-rrf-reflection Association metadata: class_name, foreign_key, association_foreign_key, association_primary_key, inverse_of, join_table.
x-rrf-association_pk The primary key of the associated class.
x-rrf-sub_fields Sub-fields used for serializing/filtering/ordering the association.
x-rrf-sub_fields_metadata Kind (column vs method) for each sub-field.
x-rrf-id_field The scalar id field (e.g., user_id, tag_ids).
x-rrf-nested_attributes_options accepts_nested_attributes_for options for the association.

Document-level (for model controllers)

Extension Description
x-rrf-primary_key The model’s primary key name.
x-rrf-callbacks The controller’s _process_action_callbacks (for tools that want to show filters).
x-rrf-bulk-create true when the controller has bulk = true — bulk create overloads the collection POST, so this is the only way to indicate it in OpenAPI.

Route-level (on each operation)

Any extra metadata you provide in extra_actions / extra_member_actions flows through to the operation spec:

self.extra_member_actions = {
  disable: {
    methods: :patch,
    metadata: {
      label: "Disable Movie",
      description: "Marks the movie as disabled without deleting it.",
    },
  },
}

Responses and Request Bodies

The framework populates standard OpenAPI responses automatically:

Including Child Controllers

By default, each controller’s document covers only its own routes. To aggregate child controllers into a single parent document (useful for generating a one-big-document view of a sub-API), set:

class Api::DemoController < ApiController
  include RESTFramework::Controller
  self.openapi_include_children = true
end

With this, OPTIONS /api/demo returns a merged document containing paths, tags, and schemas from every child controller reachable from the root.

Consuming the Document

Because the framework emits a spec-compliant OpenAPI 3.1.1 document, any standard tool works: