Use RESTful service URLs
Under REST principles, a URL identifies a resource. The following URL design patterns are considered REST best practices:
- URLs should include nouns, not verbs.
- Use plural nouns only for consistency (no singular nouns).
- Use HTTP methods (HTTP/1.1) to operate on these resources:
- Use HTTP response status codes to represent the outcome of operations on resources.
Versioning
Example of an API URL that contains a version number:
GET /v1/path/to/resource HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
Should
If an API URL does not contain a version number (anonymous version), then it should be understood that it always refers to the latest version.
Formats
Allow users to request formats like JSON or XML, for example:
http://example.gov/api/v1/magazines.json
http://example.gov/api/v1/magazines.xml
Recommended
Avoid URL designs deeper than resource/identifier/resource.
The three patterns of payload format encoding most frequently found in the wild are:
HTTP headers (e.g. Content-Type: and Accept:)
GET parameters (e.g. &format=json)
resource label (e.g. /foo.json)
Good RESTful URL examples
List of magazines:
GET /api/v1/magazines.json HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
Filtering and sorting are server-side operations on resources:
GET /api/v1/magazines.json?year=2011&sort=desc HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
A single magazine in JSON format:
GET /api/v1/magazines/1234.json HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
All articles in (or belonging to) this magazine:
GET /api/v1/magazines/1234/articles.json HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
All articles in this magazine in XML format:
GET /api/v1/magazines/1234/articles.xml HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
Specify query parameters in a comma separated list:
GET /api/v1/magazines/1234.json?fields=title,subtitle,date HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
Add a new article to a particular magazine:
POST /api/v1/magazines/1234/articles.json HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
Bad RESTful URL examples
Non-plural noun:
GET /magazine HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
GET /magazine/1234 HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
Verb in URL:
GET /magazine/1234/create HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
Filter outside of query string:
GET /magazines/2011/desc HTTP/1.1
Host: www.example.gov.au
Accept: application/json, text/javascript
Use versions
Never release an API without a version number.
Versions should be integers, not decimal numbers, prefixed with ‘v’. For example:
Good: v1, v2, v3
Bad: v-1.1, v1.2, 1.3
Maintain APIs at least one version back.
Use HTTP methods and status codes
Meaningful status codes helps consumers utilise your API.
GET /magazines
List all magazines contained within the /magazines resource
GET /magazines HTTP/1.1
Host: example.gov.au
Accept: application/json, text/javascript
A response of “200 OK” indicating that the request has succeeded.
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{...}
Status Codes:
200 OK – no error
404 Not Found – the “magazines” resource does not exist
POST /magazines
Create new magazine within the /magazines resource
POST /magazines HTTP/1.1
Host: example.gov.au
Accept: application/json, text/javascript
{...}
A response of “201 Created” indicates that the request has been fulfilled.
The URI of the new resource is provided in the response
HTTP/1.1 201 Created
Vary: Accept
Content-Type: text/javascript
{ "id": "1234" }
Batching results
If no limit is specified, return results with a default limit.
To get records 51 through 75 do this:
GET /magazines?limit=25&offset=50 HTTP/1.1
Host: example.gov.au
Accept: application/json, text/javascript
offset=50 means, ‘skip the first 50 records’
limit=25 means, ‘return a maximum of 25 records’
Information about record limits and total available count should also be included in the response. Example:
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"metadata": {
"resultset": {
"count": 227,
"offset": 25,
"limit": 25
}
},
"results": [...]