API Versioning

Grape provides robust support for API versioning, allowing you to evolve your API while maintaining compatibility for older clients. The recommended approach is to create a separate Grape::API class for each version and then mount them in a primary API class, with newer versions mounted before older ones.

# api.rb
require 'v1/api'
require 'v2/api'

class MainAPI < Grape::API
  mount V2::API
  mount V1::API
end

If a specific version is not found, Grape will pass the request to the next Rack middleware, which allows for proper cascading.

Sharing Endpoints Between Versions

To avoid duplicating code, you can define an endpoint to be available across multiple versions.

class V1 < Grape::API
  version 'v1', 'v2' # This endpoint is available in v1 and v2

  get '/shared' do
    # ...
  end
end

class V2 < Grape::API
  version 'v2'

  get '/new_in_v2' do
    # ...
  end
end

Versioning Strategies

Grape supports four strategies for clients to specify the desired API version: :path, :header, :accept_version_header, and :param. The default strategy is :path.

Path Strategy

With the path strategy, the version is part of the URL.

Configuration:

class MyAPI < Grape::API
  version 'v1', using: :path
end

Request:

curl http://localhost:9292/v1/resource

Header Strategy

This strategy uses a custom Accept header to specify the version. It follows the convention application/vnd.vendor-version+format.

Configuration:

class MyAPI < Grape::API
  version 'v1', using: :header, vendor: 'mycompany'
end

Request:

curl -H "Accept: application/vnd.mycompany-v1+json" http://localhost:9292/resource

  • Strict Mode: You can enforce the presence of a valid Accept header by setting strict: true. If the header is missing or invalid, Grape will return a 406 Not Acceptable error.
  • Quality Factors: Grape respects q values in the Accept header to determine the client's preferred format.

Accept-Version Header Strategy

This strategy uses a dedicated Accept-Version header.

Configuration:

class MyAPI < Grape::API
  version 'v1', using: :accept_version_header
end

Request:

curl -H "Accept-Version: v1" http://localhost:9292/resource

  • Strict Mode: Similar to the header strategy, setting strict: true will enforce the presence of the Accept-Version header.

Param Strategy

With the param strategy, the version is passed as a request parameter in the query string or request body.

Configuration:

class MyAPI < Grape::API
  # Default parameter is 'apiver'
  version 'v1', using: :param
end

Request:

curl http://localhost:9292/resource?apiver=v1

You can customize the parameter name using the :parameter option:

class MyAPI < Grape::API
  version 'v1', using: :param, parameter: 'v'
end

Request with custom parameter:

curl http://localhost:9292/resource?v=v1