Roughly two years ago we wrote our CloudSpokes API on the Force.com platform. Its evolved of course and the current version is a Ruby application that proxies calls to Force.com via Apex REST Services. Recently weve had a number of companies and ISVs come to us asking for advice on how to build a public API for their own Force.com org.
Most of the use cases weve seen involve one of the following:
- A company has a large development shop and doesnt want to give everyone direct access to their org. Lets say the SAP team wants some sales data and perhaps the web team needs some type of real-time integration with pricing. In this situation, you can spin up an API and expose only the data and functionality that these teams need without the need to manage their access to your org.
So how do you go about building an API with Force.com? Ill try and outline some key points but Im hoping to elaborate more in a Dreamforce session that I've proposed. First and foremost, use good API design patterns. Brian Mulloy from Apigee has a great talk from Cloudstock a couple of years ago entitled, Teach a Dog to REST that I highly recommend as a starting point.
We are going to use the CloudSpokes API as an example. Our API is written in Ruby and simply makes REST API or Apex REST calls to our Force.com org. Feel free to check out the APIs source code and even make some sample calls using our IODocs.
We host our API on Heroku and love it. There are many advantages to using Heroku including the ability to scale up and down rapidly, work in a distributed manner using Git and leverage existing add-ons such as Postgres, Redis, Memcache, Papertrail, Cloudinary, Scheduler, etc. Did I mention that they have outstanding free support, its free to get started and they also have a free usage tier?
For development you can use virtually any language that makes you feel warm and fuzzy but we chose Ruby as there are some really great gems for creating APIs, namely Rocket Pants and Grape. If you are using Node.js, Restify may give you a head start but I think Express works just as well. With Java weve had good experience building APIs using the Play! Framework but have seen other stick with good 'ol Spring.
With Ruby and Node.js you can leverage some existing open source packages for Force.com that wrap around the REST API and make language specific development much easier. I highly recommend Restforce and nforce for Ruby and Node.js, respectively. Ive used them both and they are quite awesome!
API Development
This is a big topic so Ill stick to a few subjects. Some of the key features of an API are versioning, key management, security, content negotiation, throttling and documentation.
Key management and security are fairly trivial to implement if your requirements are somewhat basic. Your API should have to ability to generate and store access keys locally that are then given out to other applications making requests. Then on each request, your API checks for the key in the header (or URL), matches it against one in the local store and either returns a 403 or processes the request normally. You can certainly get fancier by authorizing access to specific API endpoints based upon the key and such.
Even though packages such as grape, rocket pants and restify make it somewhat trivial to version your API, keep in mind that you will also need a strategy for versioning your Apex classes, Triggers, workflows, etc. inside your org. Weve gone the route of prepending version numbers to make life easier but it is something to be cognizant about.
An API is worthless without documentation so check out these resources for generating interactive docs. We use IODocs which allows us to create a live interactive documentation system by defining our resources, methods and parameters in a JSON schema. You can actually make calls against our actual API from our IODocs.
Lastly, for higher traffic APIs, there are companies that take care of the throttling, versioning, caching, key management, etc. for you. However, they are not cheap.
Advantages to Utilizing Force.com
Security FTW! This is one of the pivotal reasons to utilize Force.com for your API. Force.com security is rock solid! Why build, test and maintain your own security layer when you can leverage Force.com users, roles and profiles? Heres how weve done it. Each CloudSpokes member is a named user in Force.com so with each request we know exactly who is making the call. Our Challenge object has private sharing model. By default, every new challenge we create is shared with the 'All Members public group which includes all CloudSpokes members. Therefore, everyone has access to all challenges. When a member makes a request to see a challenge, Force.com simply checks their access and returns the record if its visible to them. When we want to restrict a challenge to a specific subset of members, we simply remove the 'All Members share and replace it with a different public group(s) or individual member(s). So now if a person that is not in the new group requests the challenge, Force.com will determine that they dont have access to the record and simply return a 404. In our API design, it just looks like a normal 404 error and is handled as usual. Simple? I know!
When you build a data intensive web application, one of the last things you typically do is build an admin UI to manage it. You spend a lot of time and money on this UI to keep it up to date and working properly. But why? Just log into your Force.com org and you have the entire admin UI automatically! Add new functionality to the API and the UI is already waiting for you. Plus your users are already comfortable with the Salesforce.com UI so theres no additional training needed.
Where should you spend most of your development effort? You can significantly drive down the cost of specialization of resources by leveraging your existing Apex developers and administrators to build your APIs business logic and functionality. Apex is fast, test coverage is required and you are able to spin up developer sandboxes to cover multiple branches and versions.
Im just going to say two words: Reports & Dashboards.
Force.com Drawbacks
One of the challenges weve encountered is writing unit tests for our Ruby API. For example, when using a test framework such as RSpec or MiniTest, you have a testing database which rolls back commits similar to running tests with Force.com. However, when running your APIs unit tests against your sandbox org, the data of course doesnt roll back as its hitting your Apex REST Services or REST API. We have had good luck using VCR which records the test suite's HTTP interactions with Force.com and replay them during future test runs. Sort of like making a mock object for an initial call to Force.com that is used for subsequent requests.
You must be aware of maintenance windows. It doesnt happen often but you do have to take into consideration that Force.com is going to be down for maintenance. Some options are to use a Heroku maintenance page or cache data locally.
Best Practices
Build your API using standards such as OAuth and REST. Sure, you can use SOAP but honestly, who likes to use SOAP any more?
This question comes up quite a bit as it concerns costs. Should you use a shared user that makes calls to Force.com for every user or should each user authenticate and make their own calls? For former is cheaper but you get much more benefit from a named user (security, chatter, audit trail, etc.). One option weve used is to tie the API key that is passed to a users credentials. Not only does this shield the credentials from the end user who may not need to know them but makes maintenance easier. Each time the user makes an API call, you look up their Force.com credentials, authenticate to get an OAuth token and the make subsequent calls with that token. The refresh token OAuth flow also works well if you want to go that route.
We highly suggest you use Apex REST Services whenever possible as they are super fast and easy to build! Unlike the REST API, you can wrap as much functionality as youd like into a single request. Weve had good results prototyping functionality using the REST API and then porting to Apex REST Services for production. You should design Apex REST Services to run as fast as possible and hand off long running requests to asynchronous processes.
You should also strive to develop both course-grained and fine-grained services to improve development and speed. For instance, we have a leaderbaord service that returns the leaderboard result for a specific time period. By default website called the API three times to get the current standing for this month, this year and all time. Call the the API three times was causing the page to load slower than we liked so we added an endpoint that returned all three time periods in a single request.
To improve performance, consider caching API calls whenever it makes sense. For example, on our CloudSpokes site, non-logged in members utilize cached GET requests from Force.com while logged in members call Force.com for each request.
Use the Streaming API instead of polling to get data out of your org. Both nforce and restforce support the Streaming API and weve had great success using both of them.
So I hope you found this useful. Perhaps the topic will get picked up for a Dreamforce session so that I can elaborate on these topics.