Hi again, in this article I will share with you some aspects I keep in mind when building an API, in the hope of helping you build a better API.

1. URL

First thing you need to understand and definitely consider when designing your API, is REST “Representational State Transfer” the ‘standard’ design architecture for building APIs.

The key principles of REST involve separating your API into logical resources. And these resources can be manipulated using HTTP requests where the method (GET, POST, PUT, DELETE, PATCH) has specific meaning.

RESTful principles have gained a wide adoption lately.

Example of RESTful API Endpoints (URL HTTP Method Operation):

As of the URL root you can choose one of the two common ways:

One more thing to keep in mind is, a RESTful API needs to have one and exactly one entry point.

However it is common for the entry point to contain some of the following information:

  • API version
  • Supported features
  • Statistics
  • A list of top-level collections
  • A list of singleton resources
  • A summary of the operating status
  • Anything else..

Finally just make sure you keep your base URL simple and intuitive.

2. Naming

Resource naming is arguably the most debated and most important concept to grasp when creating an understandable, easily leveraged API.

Naming affect the success of an API because when resources are named well, the API becomes intuitive and easy to use, thus developers will use it more and recommend it to others.

Here’s a list of some popular tips and guidelines you will need to consider:

  • use plural for all your endpoints (even when you want a single value)
  • use nouns and not verbs in endpoints (even if the do an action)
  • make sure the names are largely self-explanatory (avoid cryptic abbreviations)
  • be consistent (use the same name for the same thing everywhere)
  • avoid abbreviations (unless an abbreviation is more common than the unabbreviated term)
  • make sure it is readable and easy to use (even without documentation)

These rules applies to every string in the API not only the endpoints, but also the parameters and the payload as well.

Oe more the thing to focus on while naming resources is the case consistency (for the URI and the Body).
The case conventions for naming resources are: CamelCase, snake_case, and spinal-case.

They are all just a way of naming the resources to resemble natural language, while avoiding spaces, apostrophes and other exotic characters.

What I recommend for APIs is the snake_case (because it is commonly used by the majority of the web giants).

3. Versioning

Versioning is a must as it gives your API stability and consistency.

There are various suggested strategies to version an API, and this has been a thoroughly discussed topic in the last several years regardless of protocol or approach, be that SOAP, REST or Hypermedia.

  • Versioning within the URL:

Example: */v2/*

This is so far the most used technique for versioning. Embedding version identifiers within the URL results in URLs that change, even though the ‘resource’ itself has not changed. This violates a major tenet of API design.

And the worst problem with this technique is that it doesn’t work well with Hypermedia Controls.

  • Versioning through Content Negotiation (custom media type):

Example: Accept: version=2

Content negotiation is a mechanism defined in the HTTP specification that makes it possible to serve different versions of a document (or more generally, a resource representation) at the same URI.

Versioning with content negotiation enables you to keep the user list stable, without link bloat. It’ll simply remain as it was. This means less work for you as API developer, and fewer bytes over the wire.

  • Versioning using a query parameter:

Example: *?version=2

Using a query parameter to specify versions is not convenient (as it requires parsing of query parameters)

I do recommend using the custom media types for versioning a RESTful API.

But keep it simple by using simple indicators (e.g., v1, v2) to indicate API versions. In some cases, however, it may be useful to indicate a full semver version.

And just keep in mind the “backwards compatibility” and when the Client don’t request a specific version, you should return the original representation.

4. Responses

There’s always 2 things you need to consider when returning and API response:

  • Response Payload (this is the body of the response. It is in a standard format that will give you the application level status, the results, and if applicable, any errors)
  • HTTP Status code (this tells you at a protocol level what the status of the response is)

The Payload Format:

All responses can be returned using JSON or XML, they are both functionally equivalent, and either could be chosen.

XML is thought of as being too verbose, and harder to parse, so many-a-times, While JSON is a lightweight serialization language that is compatible with many different languages.

Currently, the most exciting of APIs provide JSON data from RESTful interfaces. XML appears to have lost the war a while ago.

But the cool thing is that you can support multiple response formats in your API at the same time, by allowing the Client to specify the format with his call.

There are 2 common ways to define you response format:

  • Through the URL

This forces the Client to add a .json or .xml file extensions to the URL (after the endpoint).

  • Through the Header

This is the most preferable way, were the Client send the format in the header:

And don’t forget that both, Client and Server, need to know which format is used for the communication. And when a custom media type is used, it is recommended the API return a response using a Content-Type header with the standard ‘application/json’ (or ‘application/xml’) media type.

The Payload Content:

Each API response is wrapped in a standard payload that contains the results of the API call, plus some additional useful information and metadata.

A very simple request:

A very simple response:

From there you might be asking yourself is there any standard to how my response should look like! and the answer is yes (but it’s not part of the REST design, as REST itself doesn’t solve this problem).

There are many standards for formatting a JSON API response, here are some of the standards:

  • JSON API it covers creating and updating resources as well, not just responses.
  • JSend it focuses on application-level (as opposed to protocol- or transport-level) messaging which makes it ideal for use in REST-style applications and APIs.
  • OData JSON Protocol is comprised of a set of specifications for representing and interacting with structured content.
  • Google JSON Style Guide these are guidelines and recommendations for building JSON APIs at Google.

There are other standards and in all cases you don’t have to follow any of the standards but just keep in mind that by following shared conventions, you increase your productivity and focus on what matters for your application.

Thus my personal preference is the JSend, as for me it seems the most popular and the easiest to implement.

I’ll talk about the HTTP Status code in the Errors section.

5. Headers

As you may know so far, REST is not a standard in itself, but it can use the HTTP standard. Therefore any REST call headers are in fact HTTP headers, a required component of the message.

HTTP header fields are components of the header section of request and response messages in the HTTP Protocol. They define the operating parameters of an HTTP transaction.

However you should not transmit actual data as a header field. Ideally, custom headers should only be used for things that do not involve the name of the resource, the state of the resource, or parameters directly affecting the resource. That leaves only true metadata about the request in custom headers.

Some conventions:

  • All fields should be name-value pairs (separated by a colon), and terminated by a new line.
  • Long lines can be folded into multiple lines; continuation lines start with either a blank space or tab character.
  • The end of the header fields is indicated by an empty line, which is then followed by the body of the message.
  • The HTTP standard does not define any size limits on headers, however most servers are configured to some limit for practical reasons; good values are 8kB per field, and 100 fields per message.
  • Use custom headers for informational purposes. Implement Clients and Servers such that they do not fail when they do not find expected custom headers.
  • There are several standards that define the required fields. An application can define any number of custom fields. By convention, custom fields started with “X-”. (however this convention was dropped after several non-standard fields became standardized).
  • If the information you are conveying through a custom HTTP header is important for the correct interpretation of the request or response, include that information in the body of the request or response or the URI used for the request. Avoid custom headers for such usages.
  • Most importantly, avoid using custom HTTP headers to change the behavior of HTTP methods. Limit any behavior-changing headers to the method POST.

6. Errors

A good API must use the HTTP status codes and try to map them cleanly to relevant standard-based codes.

The HTTP standard provides over 70 status codes to describe the return values. You don’t need them all, but there should be used at least a mount of 10. And there is no real ‘standard’ regarding their use within a REST API.

There are mainly 3 outcomes in the interaction between an App and an API:

  • Everything worked
  • The application did something wrong
  • The Client made a wrong call

Here’s a full list of the recommended HTTP Status Codes for a REST API: LINK.

Additionally the status code should work hand-in-hand with the response body to help the Client application process the request. And your API must show useful error messages in a consumable format.

Thus you need to send a minimal payload that contains an error code and message whenever an error occurred. The error format is very important and there’s a need to have a particular error format across all your responses.

Sample Error Format:

http_code (holds redundantly the HTTP error status code, so that the developer can “see” it without having to analyze the response’s header).

  • error_code (this is an internal code specific to the API “should be more relevant for business exceptions”)
  • message (short description of the error, what might have cause it and possibly a “fixing” proposal)
  • description (detailed message, containing additional data that might be relevant to the Client)

You can also include Link in the payload to points to an online resource, where more details can be found about the error. (you can remove or keep the description in that case).

The most important thing is to avoid returning 200 with an error.

7. Parameters

It’s best to keep the base resource URLs as lean as possible.

Mainly the use of query parameters with an API is for filtering, sorting and searching.

Filtering:
Filtering consists in restricting the number of queried resources by specifying some attributes and their expected values.

I propose to use directly the attribute’s name with an equal sign and the expected values, each of them separated by a comma.

Sorting:
Sorting the result of a query on a collection of resources requires two main parameters: sort (contains the names of the attributes) and desc (By default, the sorting is done in ascending order).

Searching:
If filtering does not fit our needs (to make partial or approximate matches, for instance), you need the ability to search the available resources.

A search is a sub-resource of our collection. As such, its results will have a different format than the resources and the collection itself. This allows you to add suggestions, corrections and information related to the search.

Parameters are provided the same way as for a filter, through the query-string, but they are not necessarily exact values, and their syntax permits approximate matching.

Keep your URLs simple and the URL set small. Choose one base URL for your resource and stick to it. Move complexity or optional parameters to the query string.

Example to specify what fields you want to collect from a resource:

Finally try to keep your URLs simple and the URL set small. Choose one base URL for your resource and stick to it. Move complexity or optional parameters to the query string.

8. Pagination

It is necessary to anticipate the paging of your resources in the early design phase of your API.

Pagination allows the Client to specify the number of “data per page” and the “page number” for each endpoint.

Pagination can be done in multiple ways, the most popular method used today is as follow: the Client make a request sending parameters containing details about the data he is asking for (example the Page number), then the server respond with the correct data, appending to it a ‘Paginator’ or ‘Paging’ object informing the Client on where he is now and guiding him to go next destination.

A very simple pagination object:

It is recommended as well to include next and previous URIs to help developers using your API. This is especially important when pagination is cursor based.

Alternatively you can include pagination data in the header itself. But this isn’t a complete solution as many APIs do like to return the additional pagination information, like a ‘count’ of the ‘total number’ of available results. Even though an API that requires sending a count can use a custom HTTP header like X-Total-Count.

9. Documentation

An API is only as good as its documentation. Because documentations helps in the ease of adoption of your API.

Here are some tips to consider while documenting your API:

  • Developers friendly
  • Easy to learn (provides simple examples, complete documentation)
  • Easy to use (single entry point, standard parameters)
  • Hard to misuse (explicit error message suggesting parameters values)
  • Easy to find and publically accessible
  • Show examples of complete request/response cycles
  • Provide language-specific libraries to interface with your service (There are some nice tools to automatically generate a library for you).
  • Most importantly keep it simple.

Once you release a public API, you’ve committed to not breaking things without notice. The documentation must include any deprecation schedules and details surrounding externally visible API updates. Updates should be delivered via a blog (i.e. a changelog) or a mailing list (preferably both!).

Remember developers will check out the docs before attempting any integration effort. But don’t worry if you hate to write documentations because fortunately there are many tools online that helps you generate and build your documentation such as Apiary and Swagger.

10. Authentication

Depend or your API type you may or may not need an Authentication but it is definitely one of the most important aspects of building a good API. So I will take my time to add as much information as I could.

Let’s start by listing the different types of Authentications:

Basic Authentication:
The most simple authentication technique is the Basic Authentication. The first approach that many developers used to go to is HTTP Basic, which is the most like the standard username/password approach, but instead implemented on the HTTP Request level. This technique is easy to implement and works in the browser and any other HTTP Client. But it is ludicrously insecure over HTTP and fairly insecure over HTTPS as well passwords can be stored by the browser.

Digest Authentication:
Digest is a similar approach to authentication as Basic, but is designed to improve on the security concerns. Instead of transmitting passwords in plain-text, it will calculate a MD5 hash and send that. This is generally more secure than basic auth (but still insecure over HTTP) and just like basic auth, passwords can still be stored by the browser.

OAuth Authentication:
OAuth is the biggest player on the web-based authentication scene and it’s an open standard.
The idea behind OAuth is simple, it provides client applications a ‘secure delegated access’ to server resources on behalf of a resource owner.

OAuth was first designed as a protocol, to be interoperable and easy to implement. However OAuth 1.0 was a protocol and OAuth 1.0a was as well a protocol built to be more secure even when not running over SSL while OAuth 2.0 aimed to maintain this status, but ended up being reclassified as a framework.

When dealing with OAuth, you will typically see it implemented as a 2-legged or 3-legged OAuth server. The major difference between them is that 2-legged authentication doesn’t involve another user. (For example, if you want to access a specific user’s Twitter information, you would consume the 3-legged server because an access token must be generated for the user in your application, versus just Twitter providing you a token.)

The 3-legged is more practical for real-world use.

The OAuth 3-legged authorization standard works as follow:

  1. The consumer requests a request token (usually by passing an application key and application secret).
  2. The user is then redirected to a login page, passing the request token to that page.
  3. User logs in and is redirected back to the consumer, passing the request token to the consumer’s page.
  4. The consumer exchanges the request token for an access token.
  5. If the previous request was valid, the server will return an access token to the consumer.
  6. The consumer uses the access token to make many API requests on behalf of the user (until the token expires or reaches a limit).

During this process, the authorization is processed using multiple predefined URLs, called endpoints and they are:

  1. Request URI (this endpoint passes the request token).
  2. Access URI (exchanges request token for an access token).
  3. Authorize URI (confirms that the access token is valid).

OAuth2 is the de facto standard for securing APIs and is the next evolution of the OAuth protocol. It is not backwards compatible with OAuth 1.0 and it is used by Facebook, Google and Microsoft.

To implement an OAuth Authorization Standard consider using an OAuth library for the language you are using, to make the development process quicker and easier.

Token Based Authentication

Token-Based Authentication: is prominent everywhere on the web nowadays. With almost every web company using an API, tokens are the best way to handle authentication for multiple users. Token-based authentication enables us to construct decoupled systems that are not tied to a particular authentication scheme.
The token might be generated anywhere and consumed on any system that uses the same secret key for signing the token. Before Token-Based Authentication we tend to use the Server-Based Authentication (The Traditional Method).
With Server-Based Authentication the server had to authenticate every single request made by the user (because the HTTP protocol is stateless) and to speed up this process, we used to store the logged user on a session usually in the memory. however the major problem of this method is the scalability.

There are some very important factors when choosing Token-Based Authentication for your application.

The main reasons for tokens are:

  • Stateless and scalable servers
  • Mobile application ready
  • Pass authentication to other applications
  • Extra security
  • Do not require using cookies

Example Scenario:

  1. User Requests Access with Username / Password
  2. Application validates credentials
  3. Application provides a signed token to the Client
  4. Client stores that token and sends it along with every request
  5. Server verifies token and responds with data

Every single request will require a token. The token should be sent in the HTTP header so that we keep with the idea of stateless HTTP requests.

We will also need to set our server to accept requests from all domains. (W’ll Talk about that in the CROS section).

JSON Web Tokens (JWT)

JSON Web Tokens (JWTs) are an open, industry standard RFC 7519 method for representing claims securely between two parties.

JWTs are a great authentication mechanism. They give you a structured way to declare who a user is and what they can access. They can be encrypted and signed for verification.

As well JWTs work across different programming languages: (.NET, Python, Node.js, Java, PHP, Ruby, Go, JavaScript, and Haskell).

JWTs can be passed around easily: Since they are self-contained, they are perfectly used inside an HTTP header when authenticating an API. You can also pass it through the URL.The JWT consists of 3 parts (header, payload and signature) and the JWT standard is quickly and easily interchangeable.

11. CROS

APIs are the threads that let you stitch together a rich web experience. But this experience has a hard time translating to the browser, where the options for cross-domain requests are limited to techniques like JSON-P(which has limited use due to security concerns) or setting up a custom proxy (which can be a pain to set up and maintain).

CORS (Cross-Origin Resource Sharing) is a W3C spec:

  • it allows cross-domain communication from the browser. By building on top of the XMLHttpRequest object.
  • It introduces a standard mechanism that can be used by all browsers for implementing cross-domain requests.
  • The spec defines a set of headers that allow the browser and server to communicate about which requests are (and are not) allowed.
  • If you serve public content, please consider using CORS to open it up for universal JavaScript/browser access.

Most of the heavy lifting for CORS is handled between the browser and the server. The browser adds some additional headers, and sometimes makes additional requests, during a CORS request on behalf of the Client. These additions are hidden from the Client (but can be discovered using any packet analyzer such as Wireshark).

A. BROWSER:
CORS is supported in many browsers (excluding old versions), checkout supported browser.

JQuery’s $.ajax() method can be used to make both regular XHR and CORS requests.

HTTP Request Example:

B. SERVER:
For simple CORS requests, the server only needs to add the following header to its response:

HTTP Response Example:

Check out the workflow in a big image.

12. SSL

Always use SSL. No exceptions. Today, your web APIs can get accessed from anywhere there is internet. Not all the places are secure. Many don’t encrypt communications at all, allowing for easy eavesdropping or impersonation if authentication credentials are hijacked.

Another advantage of always using SSL is that guaranteed encrypted communications simplifies authentication efforts — you can get away with simple access tokens instead of having to sign each API request.

One thing to watch out for is non-SSL access to API URLs. Do not redirect these to their SSL counterparts. Throw a hard error instead! The last thing you want is for poorly configured Clients to send requests to an unencrypted endpoint, just to be silently redirected to the actual encrypted endpoint.

13. Rate Limiting

To prevent abuse, it is standard practice to add some sort of rate limiting to an API. RFC 6585 introduced a HTTP status code 429 Too Many Requests to accommodate this.

As well try to keep track of the version/endpoints of your API being used by the Client. This can be as simple as incrementing an integer in a database each time a request is made.

Note, it is very useful to notify the consumer of their limits before they actually hit it.

14. Debugging / Testing

To debug and test your Endpoints and make sure everything is working whenever you add something new to your API, it is highly recommended to have automated testing in your code. Almost every testing framework supports API testing nowadays.

However, if you prefer or in some cases you want to perform some manual debugging for any of your Endpoints directly from your browser, you can use the Postman plugin or any similar tool (some IDE’s have these tools built in) to facilitate your mission.

Alternatively and if you are terminal geek you can use the CURL to test and debug from your terminal.

16. Date & Time

Avoid returning unix_timestamps because they don’t have timezone support. Instead use ISO-8601 for your dates as it is it’s widely-accepted standard from From the W3C to the IETF, and even XKCD. And it is easy to read, easy to parse and it has great timezone support.

Few more things to consider are:

  • Accept any timezone
  • Store and Return it in UTC
  • Don’t use time if you don’t need it

17. Hypermedia

Hypermedia, also known as HATEOAS “Hypermedia As The Engine Of Application State” is a constraint of the REST application architecture. The principle is that a client interacts with a network application entirely through hypermedia provided dynamically by application servers.

There are a lot of mixed opinions as to whether the API consumer should create links or whether links should be provided to the API.

RESTful design principles specify HATEOAS which roughly states that interaction with an endpoint should be defined within metadata that comes with the output representation and not based on out-of-band information.

One of the key constrains on REST is that a RESTful API must use hypermedia formats (the HATEOAS constraint). But unfortunately, JSON is not a hypermedia format. And there is no predefined way to deal with link discovery in JSON.

Nevertheless some standardisation is on its way to change that (but so far there’s no absolute standard as to how to represent hypermedia controls):

  • JSON-LD (A JSON-based Serialization for Linked Data), it is well supported and it is already an official W3C standard. The power of JSON-LD is that you can adopt the standard without introducing breaking changes to your API. The syntax is designed to not disturb already deployed systems and to provide a smooth migration path from JSON to JSON with added semantics.
  • HAL “Hypertext Application Language”, it is a lightweight media type that uses the idea of Resources and Links to model your JSON responses. It is becoming one of the leading hypermedia types in modern APIs. It is a personal project, formalize the expression of links in JSON so that Clients can instantly follow and discover these links without having to rely on out-of-band additional knowledge. HAL is simple to use and easy to understand.
  • Collection+JSON is a media type that standardizes the reading, writing and querying of items in a collection. Although geared to handling collections, by representing a single item as a collection of one element, Collection+JSON can elegantly handle most API responses.
  • SIREN attempts to represent generic classes of items and overcome the main drawback of HAL — support for actions. It does this admirably well and also introduces the concept of classes to your model bringing a sense of type information to your API responses.

So which one to choose!! If you are augmenting existing API responses choose JSON-LD. If you are keeping it simple choose HAL (I personally like it). If you are looking for a full featured media type choose Collection+JSON. Otherwise choose SIREN.

One obvious benefit of hypermedia controls is that it allows the server to change its URI scheme without breaking Clients. A further benefit is that it helps Client developers explore the protocol. The links give Client developers a hint as to what may be possible next.

Last thing to mention here is that Hypermedia is the third level of the Richardson Maturity Model which breaks down the principal elements of a REST approach into three steps: Resources, HTTP Verbs, and Hypermedia Controls.

18. Caching

When a Client makes requests to your API, some requests will frequently occur with the same parameters and return the same result. If we cache our request or response, we can reduce HTTP requests, which can improve performance and avoid hitting rate limits.

So the goal of caching is never having to generate the same response twice. And the main benefit of doing this is that we gain speed and reduce server load.

However there are many techniques and tools for caching. I will let you dive into this as I won’t be recommending any technique over the other.

But just keep in your mind one thing, that whenever your data gets modified, your cache must be updated immediately.

19. Coding

Finally, consider the following tips while writing the code :

  • The flexibility and extendibility of doing changes in the future without affecting the current Clients.
  • The availability of your API (make sure it can serve all your current Clients without breaking).
  • Security (do your best).
  • Avoid Return Values that demand exceptional processing (return zero length array or empty collection, not null).
  • Use an existing good quality Package (that supports your framework) to prevent your self from re-inventing the wheel.
  • Happy Coding : )

20. Tips (Use existing frameworks)

Last but not least, consider using frameworks and tools to help you get started without having to reinvent the wheel.

As a PHP developer myself, I’ve built a great framework APIATO, that provide you almost every feature you need to start writing your business logic from day one

APIATO is a A flawless framework for building scalable and testable API-Centric Apps with PHP and Laravel. It’s designed to help you build API’s faster, by providing tools and functionalities that facilitates the development of any API-Centric App.

Resources:

Follow me on Twitter @Mahmoud_Zalt

★ Software Engineer & More! ★ http://zalt.me

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store