Skip to content


Subversion checkout URL

You can clone with
Download ZIP
A Ruby-based Hypermedia API client.
Fetching latest commit...
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Frenetic Build Status

An opinionated Ruby-based Hypermedia API (HAL+JSON) client.


fre•net•ic |frəˈnetik|
fast and energetic in a rather wild and uncontrolled way : a frenetic pace of activity.

So basically, this is a crazy way to interact with your Hypermedia HAL+JSON API.

Get it? Hypermedia?



If you have not implemented a HAL+JSON API, then this will not work very well for you.


Like I said, it is opinionated. It is so opinionated, it is probably the biggest a-hole you've ever met.

Maybe in time, if you teach it, it will become more open-minded.

HAL+JSON Content Type

Frenetic expects all responses to be in HAL+JSON. It chose that standard because it is trying to make JSON API's respond in a predictable manner, which it thinks is an awesome idea.


Frenetic is going to try and use Basic Auth whether you like it or not. If that is not required, nothing will probably happen. But its going to send the header anyway.

API Description

The API's root URL must respond with a description, much like the API. This is crucial in order for Frenetic to work. If Frenetic doesn't know what the API contains, it can't parse any resource responses.

It is expected that any subclasses of Frenetic::Resource will adhere to the schema defined here.


        "description":"A widget order",

This response will be requested by Frenetic whenever a call to YourAPI.description is made. The response is memoized so any future calls will not trigger another API request.

API Resources

While HAL+JSON is awesome, not all implementations are perfect. Frenetic assumes a HAL+JSON response as built by Roar, which may not be in 100% compliance.



The problem here is that the entire response really should be wrapped in "_embedded" and "order" keys.

So until that is fixed, Frenetic will continue to be pig headed and continue to do the "wrong" thing.


Add this line to your application's Gemfile:

gem 'frenetic'

And then execute:

$ bundle

Or install it yourself as:

$ gem install frenetic


Client Initialization

  'url'          => '',
  'username'     => 'yourname',
  'password'     => 'yourpassword',
  'headers' => {
    'accept' => 'application/vnd.yoursite-v1.hal+json'
    # Optional
    'user-agent' => 'Your Site's API Client', # Optional custom User Agent, just 'cuz

Response Caching

If configured to do so, Frenetic will autotmatically cache appropriate responses through Rack::Cache. Only on-disk stores are supported right now.

Add the following Rack::Cache configuration options when initializing Frenetic:

  'cache' => {
    'metastore'   => 'file:/path/to/where/you/want/to/store/files/meta',
    'entitystore' => 'file:/path/to/where/you/want/to/store/files/meta'

The cache options are passed directly to Rack::Cache, so anything it supports can be added to the Hash.

Making Requests

Once you have created a client instance, you are free to use it however you'd like.

A Frenetic instance supports any HTTP verb that Faraday has impletented. This includes GET, POST, PUT, PATCH, and DELETE.


An easier way to make requests for a resource is to have your model inherit from Frenetic::Resource. This makes it a bit easier to encapsulate all of your resource's API requests into one place.

class Order < Frenetic::Resource

  api_client { MyAPI }

  class << self
    def find( id )
      if response = api.get( api.description.links.order.href.gsub('{id}', id.to_s) ) and response.success? response.body )
        raise OrderNotFound, "No Order found for #{id}"

The api_client class method merely tells Frenetic::Resource which API Client instance to use. If you lazily instantiate your client, then you should pass a block as demonstrated above.

Otherwise, you may pass by reference:

class Order < Frenetic::Resource
  api_client MyAPI

When your model is initialized, it will contain attribute readers for every property defined in your API's schema or description. In theory, this allows an API to add, remove, or change properties without the need to directly update your model.

Interpretting Responses

Any response body returned by a Frenetic generated API call will be returned as an OpenStruct-like object. This object responds to dot-notation as well as Hash keys and is enumerable.




For your convenience, certain HAL+JSON keys have been aliased by methods to make your code a bit more readable:

  • _embedded can be referenced as resources
  • _links can be referenced as links
  • href can be referenced as url


  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request
Something went wrong with that request. Please try again.