Notes on RESTful APIs
HTTP and REST are not new, we just misused them for a long time. A proper RESTful API should consider the following principles.
Resources
Resources are discrete entities – like entities from the Entity-Relationship Model. The web is modeled around resources. Everything is a resource, not a web page, not an application.
Resource names should be intuitive and should be nouns. Avoid Verbs in URLs.
- /resource
- represents a collection of items
- /resource/id
- represents an individual item
HTTP Methods (Verbs)
The HTTP Verbs operate on resources. Resources can be queried and altered using Verbs. Some operations are idempotent.
- GET
-
read item / collection of items
nullipotent – does not modify state, no side effects - POST
-
create item
alters state each time it is called - PUT
-
update item
idempotent – calling it multiple times has the same effect as the first time - DELETE
-
delete item
idempotent - PATCH
-
partially update item
alters state each time it is called - OPTIONS
-
display allowed verbs on a resource
nullipotent
How verbs operate on resources. Example scenario.
- /resource
-
GET collection of items
POST create new item
PUT update collection of items – this is rarely used since it updates the whole collection
DELETE collection of items
OPTIONS could display a quick help on how to query the resource - /resource/id
-
GET item
POST– using POST to create an item at an unexisting resource id is a nono
PUT (sometimes POST) update item
DELETE item
Responses
Give a proper response after each request. Applications can be much easier to develop if they get meaningful response codes.
- after GET
-
respond 200 ‘OK’ (default)
body with item - after POST (create)
-
respond 201 ‘Created’
location: /resource/id of created item
body with created item - after PUT/POST (update)
-
respond 200 ‘OK’
body with updated item - after DELETE
-
respond 204 ‘No Content’
empty body - after a bad request/unallowed method
-
respond 400 ‘Bad Request’
empty body - after encountering a problem on the server side, like a failed SQL query
- respond 500 ‘Internal Server Error’
Hypermedia
- Self describing API
-
Each response should provide links to explore the API.
Just like HTML connects multiple pages through links, API responses should have links to other resources.
Ideally, an API could be explored entirely without prior knowledge of its resources, just by knowing its base URL.
Content negotiation
- Using HTTP headers
- Accept: application/json, text/plain
- Extension in the URL
- Not RESTful, URLs are not the place for Content-Type
Versioning
- Version media types
- application/vnd.something.v1+json
- Custom header
- X-API-Version: 1
- Version in URL
-
/v1/resouce
Not RESTful, by putting the version in the URL you create separate resources
Language
- Using HTTP headers
- Accept-Language: en
Cache
Some responses can be cached.
- Expiration
-
Cache-Control
Expires - Validation
-
Last-Modified
ETag
Authentication
- OAuth
-
Industry standard
Used by most services - HTTP Auth
-
Part of the HTTP standard
Digest auth uses hashing and a nonce - Cookies
- Not for desktop apps. Last resort for web apps.
3 Comments
Hey there! A great overview, except for one thing:
> Not RESTful, by putting the version in the URL you create separate resources
Actually, the correct answer is not not ‘version’ your API, as that limits future evolvability. Think about it: what ‘version’ of Google are you using right now?
If you need to introduce non-backwards-compatible functionality, creating a separate resource is absolutely the way to go.
Thank you for the feedback. In my opinion creating another resource would mean creating another entity. What I want with versioning is just a different representation of the same entity.
Right; resources and entities do _not_ map 1-1, so that’s a bad mental model of how REST works.