Best Practices in Designing RESTful APIs

Require versioning in Accepts header

Accept: application/vnd.heroku+json; version=3

Accept serialized JSON in request bodies

Accept serialized JSON on PUT/PATCH/POST request bodies, either instead of or in addition to form-encoded data.

$ curl -X POST \
    -H "Content-Type: application/json" \
    -d '{"name": "demoapp"}'

  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "name": "demoapp",
  "owner": {
    "email": "",
    "id": "01234567-89ab-cdef-0123-456789abcdef"

Use consistent path formats

Resource names

Use the plural version of a resource name unless the resource in question is a singleton within the system (for example, in most systems a given user would only ever have one account). This keeps it consistent in the way you refer to particular resources.


Prefer endpoint layouts that don’t need any special actions for individual resources. In cases where special actions are needed, place them under a standard actions prefix, to clearly delineate them:


Downcase paths and attributes

"service_class" : "first"

Support non-id dereferencing for convenience

$ curl{app_id_or_name}
$ curl
$ curl

Minimize path nesting

Limit nesting depth by preferring to locate resources at the root path. Use nesting to indicate scoped collections


Return appropriate status codes

Refer to the for guidance on status codes for user error and server error cases.

Provide full resources where available

Provide the full resource representation (i.e. the object with all attributes) whenever possible in the response.

Provide resource (UU)IDs

Give each resource an id attribute by default. Render UUIDs in downcased 8-4-4-4-12 format, e.g.:

"id": "01234567-89ab-cdef-0123-456789abcdef"

Provide standard timestamps

Provide created_at and updated_at timestamps for resources by default, e.g:

  // ...
  "created_at": "2012-01-01T12:00:00Z",
  "updated_at": "2012-01-01T13:00:00Z",
  // ...

Use UTC times formatted in ISO8601

"finished_at": "2012-01-01T12:00:00Z"

Nest foreign key relations


  "name": "service-production",
  "owner": {
    "id": "5d8201b0..."
  // ...

Instead of:

  "name": "service-production",
  "owner_id": "5d8201b0...",
  // ...

Generate structured errors

Generate consistent, structured response bodies on errors. Include a machine-readable error id, a human-readable error message, and optionally a url pointing the client to further information about the error and how to resolve it

HTTP/1.1 429 Too Many Requests
  "id":      "rate_limit",
  "message": "Account reached its API rate limit.",
  "url":     ""

Show rate limit status

Rate limit requests from clients to protect the health of the service and maintain high service quality for other clients. You can use a to quantify request limits.

Keep JSON minified in all responses

Extra whitespace adds needless response size to requests, and many clients for human consumption will automatically “prettify” JSON output. It is best to keep JSON responses minified.

You may consider optionally providing a way for clients to retrieve more verbose response, either via a query parameter (e.g. ?pretty=true) or via an Accept header param (e.g. Accept: application/vnd.heroku+json; version=3; indent=4;).