# Mode API de Rails en 2026 : API RESTful, sérialisation et bonnes pratiques > Maîtriser le mode API de Rails avec les bonnes pratiques de conception RESTful, la sérialisation JSON avec Alba et jsonapi-serializer, les stratégies d'authentification et la gestion des erreurs dans Rails 8. - Published: 2026-06-12 - Updated: 2026-06-17 - Author: SharpSkill - Tags: ruby-on-rails, api, rest, serialization, best-practices - Reading time: 9 min --- Le mode API de Rails supprime les middlewares spécifiques au navigateur pour livrer un backend léger et rapide, conçu spécifiquement pour les API JSON. Avec Rails 8.1 et l'écosystème grandissant de bibliothèques de sérialisation, construire des API RESTful de qualité production n'a jamais été aussi fluide. > **L'essentiel en bref** > > Le mode API de Rails retire les sessions, les cookies, les vues et le middleware de l'asset pipeline. Le résultat : une stack plus légère optimisée pour les réponses JSON, idéale pour les backends mobiles, les microservices et les SPA découplées. ## Créer une application Rails 8 en mode API uniquement Créer une application Rails dédiée aux API tient en un seul flag. L'option `--api` configure `ApplicationController` pour qu'il hérite de `ActionController::API` au lieu de `ActionController::Base`, retirant plus de 15 couches de middleware sans aucune utilité dans un contexte purement API. ```ruby # Terminal command rails new order_service --api --database=postgresql ``` Cette commande génère un projet sans templates de vue, sans compilation d'assets ni cookies de session. Le fichier `application.rb` résultant inclut `config.api_only = true`, ce qui maintient la stack de middleware au strict minimum. Pour les applications Rails full-stack existantes qui nécessitent un namespace API, l'approche diffère : créer un contrôleur API de base qui hérite de `ActionController::API` et monter les routes API sous un namespace versionné. ```ruby # app/controllers/api/v1/base_controller.rb module Api module V1 class BaseController < ActionController::API before_action :authenticate_request private def authenticate_request # Token validation logic end end end end ``` Ce pattern préserve l'application full-stack intacte tout en ajoutant une couche API dédiée. ## Conception des routes RESTful et stratégies de versioning Une [conception de routes RESTful](https://guides.rubyonrails.org/routing.html) propre influence directement la facilité d'utilisation et la maintenabilité d'une API. Le DSL de routing de Rails rend l'expression des hiérarchies de ressources simple, mais quelques conventions séparent les API solides des API fragiles. ```ruby # config/routes.rb Rails.application.routes.draw do namespace :api do namespace :v1 do resources :users, only: [:index, :show, :create, :update] do resources :orders, only: [:index, :show, :create] end resources :products, only: [:index, :show] do collection do get :search end end resource :session, only: [:create, :destroy] end end end ``` Conventions clés : - **Versioning par namespace** (`/api/v1/`) plutôt que par en-tête, pour la simplicité et la mise en cache - **Imbrication superficielle** limitée à un seul niveau : `/users/:user_id/orders` fonctionne, mais `/users/:user_id/orders/:order_id/items` devrait devenir `/orders/:order_id/items` - **Ressources singulières** pour les endpoints représentant la session ou le profil de l'utilisateur courant > **Dépréciation des versions** > > Lors du retrait d'une version d'API, retourner un HTTP 410 Gone avec un corps JSON pointant vers la nouvelle version plutôt que de casser silencieusement les clients. ## Sérialisation JSON : Alba vs. jsonapi-serializer La sérialisation détermine comment les objets ActiveRecord deviennent du JSON. Le choix du sérialiseur affecte les temps de réponse, la structure de la charge utile et la flexibilité du contrat d'API. Deux bibliothèques dominent l'écosystème Rails en 2026 : [Alba](https://okuramasafumi.github.io/alba/) pour la vitesse et la simplicité, et [jsonapi-serializer](https://github.com/jsonapi-serializer/jsonapi-serializer) pour la conformité à la spécification JSON:API. ### Alba : performance sans dépendance Alba sérialise les objets Ruby jusqu'à 10 fois plus vite que les alternatives héritées comme ActiveModel::Serializer. Elle n'a aucune dépendance, ce qui la rend idéale pour les services API légers. ```ruby # app/resources/user_resource.rb class UserResource include Alba::Resource root_key :user, :users attributes :id, :email, :name, :created_at attribute :full_name do |user| "#{user.first_name} #{user.last_name}" end many :orders, resource: OrderResource # Conditional attributes based on context attribute :admin_notes, if: proc { |user, params| params[:current_user]&.admin? } end ``` ```ruby # app/controllers/api/v1/users_controller.rb class Api::V1::UsersController < Api::V1::BaseController def show user = User.includes(:orders).find(params[:id]) render json: UserResource.new(user, params: { current_user: current_user }) end def index users = User.where(active: true).page(params[:page]) render json: UserResource.new(users) end end ``` ### jsonapi-serializer : conformité stricte à la spécification Lorsque les consommateurs de l'API attendent des réponses au format [JSON:API](https://jsonapi.org/) avec les clés `data`, `type`, `attributes` et `relationships`, `jsonapi-serializer` (le fork maintenu du fast_jsonapi de Netflix) gère le formatage automatiquement. ```ruby # app/serializers/user_serializer.rb class UserSerializer include JSONAPI::Serializer set_type :user set_id :id attributes :email, :name, :created_at has_many :orders, serializer: OrderSerializer # Cache at the serializer level for high-traffic endpoints cache_options store: Rails.cache, namespace: "jsonapi", expires_in: 1.hour end ``` Le choix dépend du projet : Alba pour les API internes, les microservices et les backends mobiles où la flexibilité de la charge utile compte. jsonapi-serializer pour les API publiques où des contrats standardisés réduisent les frictions d'intégration. ## Patterns d'authentification pour les API Rails Rails 8 a introduit un [générateur d'authentification](https://guides.rubyonrails.org/security.html) intégré qui échafaude une authentification basée sur les sessions. L'adapter au mode API uniquement nécessite de remplacer les sessions par cookies par une authentification basée sur des tokens. Deux patterns dominent : le JWT pour les architectures sans état et les tokens bearer opaques pour une révocation plus simple. ### JWT avec tokens à courte durée de vie ```ruby # app/services/jwt_service.rb class JwtService SECRET = Rails.application.credentials.jwt_secret_key ALGORITHM = "HS256" def self.encode(payload, exp: 15.minutes.from_now) payload[:exp] = exp.to_i JWT.encode(payload, SECRET, ALGORITHM) end def self.decode(token) body = JWT.decode(token, SECRET, true, algorithm: ALGORITHM).first HashWithIndifferentAccess.new(body) rescue JWT::ExpiredSignature, JWT::DecodeError => e nil end end ``` ```ruby # app/controllers/concerns/jwt_authenticatable.rb module JwtAuthenticatable extend ActiveSupport::Concern included do before_action :authenticate_request end private def authenticate_request token = request.headers["Authorization"]&.split(" ")&.last decoded = JwtService.decode(token) if decoded @current_user = User.find_by(id: decoded[:user_id]) end render json: { error: "Unauthorized" }, status: :unauthorized unless @current_user end def current_user @current_user end end ``` Des tokens d'accès à courte durée de vie (15 minutes) associés à une rotation des refresh tokens offrent un équilibre sécurisé. Le token d'accès reste sans état, tandis que les refresh tokens stockés en base de données permettent la révocation lors d'un changement de mot de passe ou d'une déconnexion. ### Tokens bearer opaques Pour des API plus simples où une recherche en base de données par requête est acceptable, `has_secure_token` offre une approche directe : ```ruby # app/models/user.rb class User < ApplicationRecord has_secure_password has_secure_token :api_token def regenerate_api_token! regenerate_api_token end end ``` Les tokens opaques simplifient la révocation (supprimer ou régénérer le token) mais exigent une requête en base de données à chaque appel authentifié. ## Gestion structurée des erreurs à travers l'API Des réponses d'erreur cohérentes séparent les API professionnelles des prototypes. Un gestionnaire d'erreurs centralisé empêche Rails de retourner des pages d'erreur HTML et garantit que chaque échec retourne du JSON structuré. ```ruby # app/controllers/concerns/error_handler.rb module ErrorHandler extend ActiveSupport::Concern included do rescue_from ActiveRecord::RecordNotFound, with: :not_found rescue_from ActiveRecord::RecordInvalid, with: :unprocessable_entity rescue_from ActionController::ParameterMissing, with: :bad_request end private def not_found(exception) render json: { error: "not_found", message: "Resource not found", details: exception.message }, status: :not_found end def unprocessable_entity(exception) render json: { error: "validation_failed", message: "Validation failed", details: exception.record.errors.full_messages }, status: :unprocessable_entity end def bad_request(exception) render json: { error: "bad_request", message: "Missing required parameter", details: exception.message }, status: :bad_request end end ``` Inclure ce concern dans le contrôleur API de base. Chaque endpoint retourne alors des erreurs JSON prévisibles avec des codes de statut HTTP appropriés, des types d'erreur lisibles par machine et des messages lisibles par l'humain. > **Ignorer le CSRF pour l'authentification par token** > > Les contrôleurs API utilisant une authentification basée sur des tokens doivent ignorer la vérification CSRF. Ajouter `skip_before_action :verify_authenticity_token` ou hériter de `ActionController::API`, qui n'inclut pas le middleware CSRF par défaut. ## Pagination et optimisation des réponses Les requêtes sans limite sont le chemin le plus rapide vers la dégradation des performances. Chaque endpoint de liste devrait paginer les résultats et communiquer clairement les métadonnées de pagination. ```ruby # app/controllers/api/v1/products_controller.rb class Api::V1::ProductsController < Api::V1::BaseController def index products = Product .where(active: true) .order(created_at: :desc) .page(params[:page]) .per(params[:per_page] || 25) render json: { data: ProductResource.new(products).serializable_hash, meta: { current_page: products.current_page, total_pages: products.total_pages, total_count: products.total_count } } end end ``` Au-delà de la pagination, trois optimisations font une différence mesurable sur les temps de réponse de l'API : - **L'eager loading** avec `includes` ou `preload` élimine les [requêtes N+1](/blog/ruby-on-rails/activerecord-fixing-n-plus-1-query-problems) qui multiplient les allers-retours vers la base de données - **Sélectionner uniquement les colonnes nécessaires** avec `.select(:id, :name, :price)` quand les sérialiseurs n'utilisent qu'un sous-ensemble des attributs du modèle - **Les en-têtes de cache HTTP** via `stale?` et `fresh_when` permettent aux clients et aux CDN de mettre en cache les réponses sans logique personnalisée ## Tester les endpoints d'API Rails avec RSpec Les tests d'API devraient vérifier les codes de statut, la structure des réponses et les barrières d'authentification. Les [request specs](https://guides.rubyonrails.org/testing.html) dans RSpec traversent la stack de middleware complète, ce qui en fait la représentation la plus proche du comportement réel d'une API. ```ruby # spec/requests/api/v1/users_spec.rb RSpec.describe "Api::V1::Users", type: :request do let(:user) { create(:user) } let(:token) { JwtService.encode(user_id: user.id) } let(:headers) { { "Authorization" => "Bearer #{token}" } } describe "GET /api/v1/users/:id" do it "returns the user with correct structure" do get "/api/v1/users/#{user.id}", headers: headers expect(response).to have_http_status(:ok) json = JSON.parse(response.body) expect(json["user"]).to include( "id" => user.id, "email" => user.email, "name" => user.name ) end it "returns 401 without authentication" do get "/api/v1/users/#{user.id}" expect(response).to have_http_status(:unauthorized) end it "returns 404 for non-existent user" do get "/api/v1/users/0", headers: headers expect(response).to have_http_status(:not_found) json = JSON.parse(response.body) expect(json["error"]).to eq("not_found") end end end ``` Ces tests couvrent les trois scénarios que chaque endpoint d'API devrait gérer : la structure d'une réponse réussie, l'application de l'authentification et le format des réponses d'erreur. ## Fonctionnalités d'API de Rails 8.1 qui valent l'adoption Rails 8.1 (publié en octobre 2025) ajoute des capacités directement pertinentes pour le développement d'API : - **Les Continuable Jobs** permettent aux tâches d'arrière-plan de longue durée (imports de données, traitement par lots) de reprendre depuis le dernier point de contrôle après des déploiements ou des redémarrages, éliminant le travail gaspillé dans les [pipelines de jobs d'arrière-plan](/technologies/ruby-on-rails/interview-questions/active-job-background-jobs) - **Le Structured Event Logging** via `Rails.event.notify(...)` émet des événements consommables par les plateformes APM (Datadog, New Relic) sans code d'instrumentation personnalisé - **Les Deprecated Associations** peuvent être marquées avec les modes `:warn`, `:raise` ou `:notify`, aidant les équipes à retirer progressivement les relations héritées dans de grandes bases de code d'API Ces fonctionnalités réduisent le boilerplate dans les projets d'API et améliorent l'observabilité dès le départ. Le [guide de migration Rails 8](/blog/ruby-on-rails/ruby-on-rails-8-new-features-migration-guide) couvre le parcours de mise à niveau complet. ## Conclusion - **Utiliser le mode `--api`** pour les services API dédiés afin d'éliminer le middleware superflu et réduire la latence de réponse - **Choisir un sérialiseur adapté au contrat** : Alba pour la vitesse et la flexibilité, jsonapi-serializer pour une conformité stricte à JSON:API - **Implémenter une authentification par token** avec des JWT à courte durée de vie et une rotation des refresh tokens, ou des tokens bearer opaques pour des besoins de révocation plus simples - **Centraliser la gestion des erreurs** dans un concern partagé pour que chaque endpoint retourne du JSON structuré avec des types d'erreur cohérents - **Paginer chaque endpoint de liste** et appliquer l'eager loading pour éliminer les requêtes N+1 avant qu'elles n'atteignent la production - **Tester avec des request specs** sur les trois scénarios fondamentaux : structure de succès, application de l'authentification et format des erreurs - **Adopter les fonctionnalités de Rails 8.1** comme les continuable jobs et les événements structurés pour améliorer la fiabilité et l'observabilité des services API --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/fr/blog/ruby-on-rails/rails-api-mode-restful-serialization-best-practices