tags:

views:

135

answers:

7

I am in the planning and early coding stages of writing my first full-fledged API for a large scale we application. I have used several APIs over the years but this is the first time I have been asked to construct something that will allow programmatic interaction on this level.

I have done quite a bit of research looking for best practices and such and have identified what I THINK will offer a fairly flexible response communication system.

My questions are:

Is this what you expect to see as API interaction?

Did I miss anything important?

Explanation of API:

I am going to be using HTTP Type 1 protocol for communication and a unique API key for authentication.

I am expecting this to come through CURL requests over an SSL connection.

Example of Successful (200 OK) XML Response (rate limit request):

<?xml version="1.0" encoding="UTF-8"?>
<node>
    <short_message>Request Complete</short_message>
    <long_message>Rate Limit Status Response</long_message>
    <response_data>
        <rate_limit>40</rate_limit>
        <rate_used>31</rate_used>
    </response_data>
</node>

Example of Failed XML Response (Will be sent under appropriate 400/500 Header);

<?xml version="1.0" encoding="UTF-8"?>
<node>
    <error_code>1201</error_code>
    <short_message>API Error</short_message>
    <long_message>The requested API version (1.5) is invalid</long_message> 
</node>

Additionally I am setting up the error codes to be used in search-able documentation for easing the migraines of other developers. Pass/Fail of request will be given through appropriate HTTP codes--Success (200), bad requests (400), method not found (404), authentication failed (403), etc...

I am also using version based endpoints so that any code changes will not require external code changes.

Finally devs will be able to request all responses in either XML, JSON, or PHP serialized arrays.

The internals of my code are very simple. All data is passed through POST (probably using CURL or some alternative) including a unique API key. That API key is linked to a user in the system which will then allow the internal methods to execute a limited set of functions that are enabled for that specific user.

I am following the API 'Golden Rule'--"Always add, never delete".

So.. what else should I consider and what have I missed?

A: 

The XML looks nice. But to say more about the inner Logic we need more Details than just the XML.

streetparade
@streetparade - I am going to make some adjustments now and extend the question a bit. Thanks!
angryCodeMonkey
A: 

The best API you can use as an example is the API your coding in. Use the same naming conventions and casing.

Also, try to build sample applications using your API and you'll quickly discover its shortcomings.

Sir Psycho
+2  A: 

A few things:

1) Putting response headers into different places - HTTP header AND response_code - will definitely cause confusion. Some developers will check it in one place, some in the other. If you want to go with that route, absolutely make sure that the response codes are identical between HTTP headers and the returned XML.

2) Your server does NOT have to return the API version with every response. You're wasting bits on the wire. If the client wants a specific version of the API, have them send it up in the request. You don't have to send it back to them.

3) Combine response_code and request_status. Look at how HTTP does it: 200-299 means success. 400-499 means client is dumb. 500-599 means server is screwed up.

Alex
@Alex - Good call on the version number--I believe I saw this in another API a while back and thought it a good idea, but point well taken that it is superfluous. Also, I am going to use the HTTP codes instead of SUCCESS/FAILURE but am keeping the error codes to help with documentation of the API.
angryCodeMonkey
A: 

Have you considered using versioned endpoints? They may require a bit more planning and maintenance on your part, but your users will love not having to rewrite their code every time you decide to change parameters / return values.

If you come up with a plan to deprecate and then remove old versions, this shouldn't prove too painful.

jasonbar
@jasonbar - Actually, I forgot to mention that in my original post, but I am also doing version based endpoints for that very reason.. Thanks!
angryCodeMonkey
+2  A: 

Shane,

I am assuming your goal is to build a RESTful API - is that true?

My answer applies only if this assumption is true - I am not trying to criticize your design, just its RESTfulness.

REST defines 4 interface constraints which your design must adhere to in order to be RESTful. Your design violates at least three of them and hence is not RESTful. This is not necessarily a bad thing in itself but it is important that you understand that your system will probably not have the properties you expect it to have.

I'll try to get you started with a short answer below, but please have a look at http://nordsc.com/ext/classification_of_http_based_apis.html where I discuss this issue a bit more. You can then probably break all this down to smaller questions and come back here or visit rest-discuss on Yahoo groups: http://tech.groups.yahoo.com/group/rest-discuss/

Now short comments to your design:

  1. You should not use your own response codes but only use the ones provided by HTTP. You could make up your own ones, but those must be generally applicable and not be specific to your application or interaction.

  2. You should use a specific media type, not only application/xml. If none of the existing types match your need (or can be extended to do so), you can develop your own. In fact, the major design activity should be spend on the media type. It is where your domain semantics live.

  3. You must adhere to the hypermedia constraint to be truly RESTful. This means that the client should be provided with links and/or forms to discover what it can do next.

Using the classification referenced above, you API seems like a HTTP-based Type I ( http://nordsc.com/ext/classification_of_http_based_apis.html#http-type-one ) assuming you do not put actions in your URIs, which would make it RPC URI-Tunneling ( http://nordsc.com/ext/classification_of_http_based_apis.html#uri-rpc )

I hope that helps you with your overall goal.

Jan

Jan Algermissen
@Jan Algermissen- (+1) Wow, excellent answer--I am going to work through all of these links tonight. You are correct that I am leaning toward the HTTP-based Type I that you mentioned. I am trying to make it as accessible as possible for developers and felt that would be the best way--going to change my tag from Restful to something else. Do you see any drawbacks to this over REST? I will still be using POST over GET to get data securely.
angryCodeMonkey
Glad it was helpful. I am obviously pro-REST through and through, but I also understand that the learning curve is high. I think that as long as you know what the properties of the system will be you are safe doing what fits the requirements best. So if long-term maintenance cost is not among your primary issues, you are likely able to live with the tight coupling. It is just important to be aware of it. Hence my 'table' because I felt that people are really started to get confused over all this :-)Your last sentence I did not understand, can you re-word?
Jan Algermissen
@Jan Algermissen - I should have expanded on that a bit! I am planning on using a SINGLE url for all API calls instead of calling different URLs for each method/function. So you would call http://www.domain.com/api/execute/ for everything and then POST all required information to that script. One of the required parameters is the method to execute. I hope that makes more sense! Also, I hope that isn't too non-standard it just seems that it would make development easier rather than having to keep up with multiple script calls.
angryCodeMonkey
Using a single URL for all API calls reduces your architecture to pure messaging. One effect of this is that you loose the HTTP-built-in caching. You also loose all visibility because you are not able to use HTP methods correctly anymore. Basically you are treating HTTP as a transport protocol and not as an application protocol (which it actually is). To help understand: TCP already is a transport protocol - why would you layer another one on top of it?Without meaning to insult you: you cannot really do any worse if you are using HTTP. I'd do a little re-design.
Jan Algermissen
In Addition: what you are planning to to is a home grown SOAP-over-HTP. IOW, while you will have all the negative impact of that approach you'll also have the burden of designing your own (little) SOAP.Suggestion: dig a little more and go for HTTP-based Type I ( http://nordsc.com/ext/classification_of_http_based_apis.html#http-type-one ). The learning curve is reasonable but the gain will be enormous. HTH.
Jan Algermissen
+1  A: 

If you're really building REST services, consider this:

  • request_status, should be drop in favor of html response code (at least 200: OK, 400: Bad Request, 401: Unauthorized, 403: Forbidden and 500: Internal Error), response_code may be needed to find in your documentation an explanation of the problem.
  • You want to provide different format, the format of the response should not depend of the url but of the Accept header
mathroc
@mathroc - (+1) Good deal, I have seen several similar comments so I am going to drop the response_status in lieu of HTTP response codes
angryCodeMonkey
A: 

About you "single URL/endpoint" idea - keep in mind that with Apache you can serve a potentially unlimited number of URLs from a single script via URL rewriting rules. This means that with a properly defined .htaccess file in the directory of your "endpoint" script you can have your web server automatically "map" incoming requests like this, for example:

/foo/slice/1234 => /foo/?action=slice&oid=1234
/foo/dice/3456  => /foo/?action=dice&oid=3456
/foo/chop/4567  => /foo/?action=chop&oid=4567

This can be very helpful if you decide that you want to serve "RESTful" URLs after all (and can be made to work with HTTP request modes GET, POST, PUT, DELETE, HEAD).

Peter