Spec modules

Define

defmodule MyAppWeb.ApiSpec do
  use AshOaskit,
    domains: [MyApp.Blog],
    title: "My API",
    api_version: "1.0.0"
end

Customize

defmodule MyAppWeb.ApiSpec do
  use AshOaskit, domains: [MyApp.Blog]

  @impl AshOaskit.Spec
  def modify_spec(spec) do
    put_in(spec, ["components", "securitySchemes"], %{
      "bearerAuth" => %{"type" => "http", "scheme" => "bearer"}
    })
  end
end

Serve (Phoenix or Plug.Router)

use AshOaskit.Router,
  spec: MyAppWeb.ApiSpec,
  open_api: "/openapi",
  redoc: "/redoc"

Serve both OpenAPI versions

use AshOaskit.Router,
  spec: [
    {"3.1", MyAppWeb.ApiSpecV31},
    {"3.0", MyAppWeb.ApiSpecV30}
  ],
  open_api: "/openapi"

Dev: regenerate on reload

# config/dev.exs
config :ash_oaskit, cache_specs: false

Validate in tests

assert {:ok, _} = AshOaskit.validate(MyAppWeb.ApiSpec.spec())
Oaskit.build_spec!(MyAppWeb.ApiSpec)

One-off generation

In code

spec = AshOaskit.spec(domains: [MyApp.Blog])
spec = AshOaskit.spec_30(domains: [MyApp.Blog])
spec = AshOaskit.spec_31(domains: [MyApp.Blog])

With full options

AshOaskit.spec(
  domains: [MyApp.Blog],
  version: "3.1",
  title: "My API",
  api_version: "2.0.0",
  description: "Blog API",
  servers: ["https://api.example.com"]
)

Validate a spec map

{:ok, validated} = AshOaskit.validate(spec)
validated = AshOaskit.validate!(spec)

Mix tasks

Export a spec module (preferred)

mix openapi.dump MyAppWeb.ApiSpec \
  --pretty -o priv/static/openapi.json

Generate without a spec module

mix ash_oaskit.generate \
  --domains MyApp.Blog,MyApp.Accounts \
  --version 3.1 \
  --output openapi.json

Install

mix igniter.install ash_oaskit

Making things appear in the spec

Fields must be public

attribute :title, :string do
  public? true
end

Only public? true attributes, calculations, aggregates, and relationships appear in generated specs — matching what AshJsonApi serializes.

Request bodies follow the action

create :create do
  accept [:title, :body]
end
# -> PostCreateInput documents exactly title + body

Descriptions propagate

create :create do
  description "Creates a blog post"
end
# -> operation description