Another option, which I've used to good effect, is to use the content tree, the "star" item, and a sublayout/layout combination dedicated to this purpose:
[siteroot]/API/*/*/*/*/*/*/*/*/*
The above path allows you to have anywhere between 1 and 9 segments - if you need more than that, you probably need to rethink your process, IMO. This also retains all of the Sitecore context. Sitecore, when unable to find an item in a folder, attempts to look for the catch-all star item and if present, it renders that item instead of returning a 404.
There are a few ways to go about doing the restful methods and the sublayout (or sublayouts if you want to segregate them by depth to simplify parsing).
You can choose to follow the general "standard" and use GET, PUT, and POST calls to interact with these items, but then you can't use Sitecore Caching without custom backend caching code). Alternately, you can split your API into three different trees:
[siteroot]/API/GET/*/*/*/*/*/*/*/*/*
[siteroot]/API/PUT/*/*/*/*/*/*/*/*/*
[siteroot]/API/POST/*/*/*/*/*/*/*/*/*
This allows caching the GET requests (since GET requests should only retrieve data, not update it). Be sure to use the proper caching scheme, essentially this should cache based on every permutation of the data, user, etc., if you intend to use this in any of those contexts.
If you are going to create multiple sublayouts, I recommend creating a base class that handles general methods for GET, PUT, and POST, and then use those classes as the base for your sublayouts.
In your sublayouts, you simply get the Request object, get the path (and query if you're using queries), split it, and perform your switch case logic just as you would with standard routing. For PUT, use Response.ReadBinary(). For POST use the Request.Form object to get all of the form elements and iterate through them to process the information provided (it may be easiest to put all of your form data into a single JSON object, encapsulated as a string (so .NET sees it as a string and therefore one single property) and then you only have one element in the post to deserialize depending on the POST path the user specified.
Complicated? Yes. Works? Yes. Recommended? Well... if you're in a shared environment (multiple sites) and you don't want this processing happening for EVERY site in the pipeline processor, then this solution works. If you have access to using MVC with Sitecore or have no issues altering the pipeline processor, then that is likely more efficient.
One benefit to the content based method is that the context lifecycle is exactly the same as a standard Sitecore page (logins, etc.), so you've got all the same controls as any other item would provide at that point in the lifecycle. The negative to this is that you have to deal with the entire page lifecycle load before it gets to your code... the pipeline processor can skip a lot of Sitecore's process and just get the data you need directly, making it faster.