Building APIs with Rails API Mode

· 4 min read · Updated March 17, 2026 · intermediate
rails api rest rails-api json ruby

Rails API Mode is a way to generate a Rails application that’s optimized for building APIs. It strips away the unnecessary components of a full Rails application — like views, helpers, and asset pipelines — leaving you with a lean, focused API backend.

What Is Rails API Mode?

When you create a new Rails app with --api, you get a slimmed-down version that includes only what you need for an API:

  • Controllers that respond to JSON requests
  • Models for database interactions
  • Routing for RESTful endpoints
  • Middleware tailored for API requests (no sessions, cookies, or browser-specific stuff)

The key difference from a full Rails app is what’s excluded:

Full Rails AppAPI Mode
ActionViewExcluded
ActionMailerExcluded
Asset PipelineExcluded
Session MiddlewareExcluded
CookiesExcluded
Flash messagesExcluded

This means faster boot times, smaller memory footprint, and a more focused codebase.

Creating an API-Only App

Generate a new API-only Rails application:

rails new my_api --api

This creates an app with the API-focused stack. You can verify it by checking config/application.rb:

module MyApi
  class Application < Rails::Application
    config.api_only = true
  end
end

Converting an Existing App

If you have a full Rails app and want to convert it to API mode, you can do that too.

Step 1: Set API Mode in Config

In config/application.rb:

config.api_only = true

Step 2: Use API Controllers

Instead of ActionController::Base, use ActionController::API as your base class:

# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
end

ActionController::API is a lighter weight controller that includes only the essentials for handling requests — no view rendering, no session management, no cookies.

Step 3: Remove Unnecessary Middleware

In config/application.rb, you can remove middleware you don’t need:

module MyApp
  class Application < Rails::Application
    config.api_only = true
    
    # Remove these if not using:
    config.middleware.delete ActionDispatch::Cookies
    config.middleware.delete ActionDispatch::Session::CookieStore
    config.middleware.delete ActionDispatch::Flash
  end
end

Building Your First API Endpoint

Let’s create a simple RESTful resource. Say we want an API for managing users.

Generate a Resource

rails generate scaffold User name:string email:string

This creates the model, controller, and routes. The controller will respond to JSON by default.

Check the Routes

rails routes

You’ll see standard RESTful routes:

users GET    /users(.:format)          users#index
users POST   /users(.:format)          users#create
user  GET    /users/:id(.:format)      users#show
user  PATCH  /users/:id(.:format)      users#update
user  PUT    /users/:id(.:format)      users#update
user  DELETE /users/:id(.:format)      users#destroy

Test the API

Start the server and make a request:

rails server -p 3000
# Create a user
curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'

# List users
curl http://localhost:3000/users

# Get a specific user
curl http://localhost:3000/users/1

The responses will be JSON automatically.

Customizing JSON Rendering

Using Jbuilder

Rails includes Jbuilder for building complex JSON responses. Create a view file:

# app/views/users/show.json.jbuilder
json.id @user.id
json.name @user.name
json.email @user.email
json.created_at @user.created_at.iso8601

Using Active Model Serializers

For more control, add the active_model_serializers gem:

gem 'active_model_serializers'

Generate a serializer:

rails generate serializer User
# app/serializers/user_serializer.rb
class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :email, :created_at

  def created_at
    object.created_at.iso8601
  end
end

In your controller, rendering automatically uses the serializer:

class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    render json: @user
  end
end

Authentication

APIs typically need authentication. Here are common approaches:

Token Authentication

Implement a simple token-based auth:

# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  before_action :authenticate_request

  private

  def authenticate_request
    token = request.headers['Authorization']&.split(' ')&.last
    @current_user = User.find_by(api_token: token)
    
    render json: { error: 'Unauthorized' }, status: :unauthorized unless @current_user
  end
end

Using Devise Token Auth

For production apps, use a gem like devise_token_auth:

gem 'devise_token_auth'

This provides full token-based authentication out of the box.

Error Handling

API mode still supports standard Rails error handling, but you might want custom JSON error responses:

# app/controllers/application_controller.rb
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
rescue_from ActiveRecord::RecordInvalid, with: :render_validation_error

private

def render_not_found(exception)
  render json: { error: exception.message }, status: :not_found
end

def render_validation_error(exception)
  render json: { errors: exception.record.errors.full_messages }, status: :unprocessable_entity
end

CORS Configuration

If your API will be accessed from browsers on different domains, configure CORS:

# Gemfile
gem 'rack-cors'
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'http://localhost:3001' # Your frontend domain
    
    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options]
  end
end

Versioning Your API

As your API evolves, you’ll want version it. A common approach:

# config/routes.rb
namespace :api do
  namespace :v1 do
    resources :users
  end
end

This creates routes like /api/v1/users.

Organize your controllers:

# app/controllers/api/v1/users_controller.rb
module Api
  module V1
    class UsersController < ApplicationController
      # Your logic here
    end
  end
end

When to Use API Mode

Rails API Mode is ideal when:

  • Building a JSON API for a JavaScript frontend (React, Vue, etc.)
  • Creating a mobile app backend
  • Providing an API for third-party integrations
  • Microservices that don’t need views

Stick with full Rails when:

  • You need server-side rendering (SSR)
  • You want the asset pipeline
  • You’re building a traditional web app

See Also