Return to site

How to (and how not to) design REST APIs by Jeff Schnitzer

· api,programmmer

Rule #0: DON'T get pedantic

Don't worry about what is or isn't REST; focus on building pragmatic, useful APIs.

Rule #1: DO use plural nouns for collections

👍 GET /products/{product_id}
👎 GET /product/{product_id}

Rule #2: DON'T add unnecessary path segments

👍 GET /v3/application/listings/{listing_id}
👎 GET /v3/application/shops/{shop_id}/listings/{listing_id}/properties

The {listing_id} is globally unique; there's no reason for {shop_id} to be part of the URL.

Rule #3: DON'T add .json or other extensions to the url


Rule #4: DON'T return arrays as top-level responses

👍 GET /things returns:{ "data": [{ ...thing1...}, { ...thing2...}] }

👎 GET /things returns:
[{ ...thing1...}, { ...thing2...}]

Rule #5: DON'T return map structures

👍 GET /things returns:{
"data": [
{ "id": "KEY1", "foo": "bar" },
{ "id": "KEY2", "foo": "baz" },
{ "id": "KEY3", "foo": "bat" }

👎 GET /things returns:
"KEY1": { "id": "KEY1", "foo": "bar" },
"KEY2": { "id": "KEY2", "foo": "baz" },
"KEY3": { "id": "KEY3", "foo": "bat" }

Rule #6: DO use strings for all identifiers


Rule #7: DO prefix your identifiers

Stripe's identifiers have two-letter-plus-underscore prefixes.

For customer, it is something like cus_sd9f87gds987, for subscription it is sub_df987gds98fg, for invoice it is in_d98fg7d987fg, and so on. You got the idea.

Rule #8: DON'T use 404 to indicate "not found"

Returning HTTP 404 for "thing not found" is almost like returning HTTP 500 - it could mean the thing doesn't exist, or it could mean something went wrong; the client cannot be sure which.

Rule #9: BE consistent

Please please do your best to keep fields consistent among objects with similar meanings. 

Rule #10: DO use a structured error format

My error formats tend to look something like this, roughly shaped like a (Java) exception:

{ "message": "You do not have permission to access this resource",
"type": "Unauthorized",
"types": ["Unauthorized", "Security"],
"cause": { ...recurse for nested any exceptions... }


Rule #11: DO provide idempotence mechanisms


Rule #12: DO use ISO8601 strings for timestamps

Someone glancing at "2023-12-21T11:17:12.34Z" might notice that it's a month in the future; someone glancing at 1703157432340 will not.

#rest #api #programming #goodPractices #developer