Introducing Our New API
A public facing API has been a much requested feature of Engine Yard Cloud. We’ve had this feature available for quite a long time, but this API has a number of drawbacks. Some time ago, we decided that it was time for something new. We call it the Core API.
Why do we call it the Core API?
Well, because this API presents an interface to the core of our product!
We have been using this internally for quite some time, and it has gone through a number of major revisions. Finally, we are happy with the stability and decided it was time to release it to our customers.
If you’re currently using our existing API, this one is a bit different but hopefully easier to use. We do plan to retire the existing API, however we don’t have a set date for retirement at this time.
We’ve written a Ruby gem, ey-core, that makes working with our new API a breeze. It’s an open source gem, and if you would like to make improvements, we welcome your contributions! Head along to the GitHub repository to get started.
The purpose of this post is to look at the API design and help familiarize you with the tooling we already have in place, as well as help you get started creating your own tooling if you desire.
Design
Security was of the utmost importance during this API redesign. To facilitate that, we used the Pundit library to handle the authorizations. This tool has proven to be rock solid.
We also designed the Core API with consistency in mind. This means RESTful routes and consistent parameter passing throughout.
The credentials needed for working with the Core API are the same credentials you already use with the engineyard gem. If you don’t already have those, grab that gem, run ey login
and then grab the token from the .eyrc
file in your home directory.
GET requests
The Core API returns JSON by default, with XML available as an alternative. Switching between them is as easy as modifying your HTTP Accept header.
You can expect a consistent format across related requests.
For example, if I wanted to see all of the environments I have available, I could issue this command:
curl 'https://api.engineyard.com/environments' -v -H "Accept: application/json" -H "X-EY-TOKEN: my_token"
This returns a JSON blob with the following format:
{"environments": [{}]}
Similarly, if I choose to query a specific environment, I could run:
curl 'https://api.engineyard.com/environments/12345' -v -H "Accept: application/json" -H "X-EY-TOKEN: my_token"
This would return:
{"environment":{“id”:12345,...}}
With this API design, you can expect consistency throughout.
POST, PUT, and DELETE Requests
For POST and PUT requests, you will need to send a JSON encoded body with the request parameters. See our developer docs for more information.
Whenever possible, we create, update, or destroy the resource immediately. However, some operations may need to be completed asynchronously. For example: booting servers.
To handle these asynchronous operations, we have a request object we return to you. You can poll this object to get information about what is happening in the background.
The request object looks something like this:
{
"request": {
"id": "11111111 - 2222 - 3333 - 4444 - 555555555555",
"type": "boot_environment",
"created_at": "2015-11-24T19:20:06+00:00",
"started_at": "2015-11-24T19:20:06+00:00",
"finished_at": null,
"message": null,
"successful": null,
"updated_at": "2015-11-24T19:20:40+00:00",
"read_channel": null,
"stage": "information about where the request is currently",
"dependencies": "[https://api.engineyard.com/requests/11111111-2222-3333-4444-555555555555/dependencies](https://api.engineyard.com/requests/11111111-2222-3333-4444-555555555555/dependencies)",
"stages": "[https://api.engineyard.com/requests/11111111-2222-3333-4444-555555555555/stages](https://api.engineyard.com/requests/11111111-2222-3333-4444-555555555555/stages)",
"account": "[https://api.engineyard.com/accounts/account_id](https://api.engineyard.com/accounts/account_id)",
"exception": null,
"requester": "information about what requested the operation (i.e. a user, or a different request)",
"messages": "[https://api.engineyard.com/requests/11111111-2222-3333-4444-555555555555/messages](https://api.engineyard.com/requests/11111111-2222-3333-4444-555555555555/messages)",
"progress": false,
"resource": false // false when the operation is not complete, a link to the resource when it is
}
}
Using this request object design throughout the API allows for consistent modeling of resource creation in your scripts.
Conclusion
We’ve put a lot of time and effort into this API. We are excited to get customers using it, and most importantly, to receive your feedback. Please don’t hesitate to reach out.
Share your thoughts with @engineyard on Twitter