Design a better web api

04 Apr, 2018API

I don't know if there are people around you who often hold this point of view - "The interface can be tuned, but the user can't see it anyway, don't care if it is standard or not." In fact, API design is not intended for users, but for developers. Doing a good job of API design does not need to delay a lot of time, but the API design is sufficiently standardized so that developers can see the meaning and usage of each field of each model at a glance. On the one hand, it can reduce a lot of work of writing API documents. The amount of data can greatly reduce the communication cost of the docking parties; on the other hand, a good API design is easy to abstract, and the docking parties can reuse a large amount of code. The interfaces are roughly the same, but they cannot be abstracted. You must copy and paste each and make some modifications. This situation will also be improved.

Let's first look at some counterexamples of Web API design, most of which are encountered in actual work:

  • Use the same name for different projects
  • Use api1, api2, api3... as the prefix of the API domain name of different projects
  • Interface and field camel case naming and underscore naming are mixed
  • Use 2 and 4 to represent to and for
  • Looks RESTful, but only POST and GET
  • Without PATCH, each field modification of the data must correspond to a new interface
  • The format of the request data form-data and JSON are mixed
  • There are almost no resource-type interfaces, all interfaces are verbs + model names
  • New operations are called addModel, createModel, upload, generateModel, etc.
  • List query operations are called listModel, queryModel, modelList, list, getAll, all, etc.
  • A single query operation is called findModel, searchModel, and get.
  • The delete operation is called removeModel and delete, but it does not use the HTTP DELETE method
  • Although there is a version number in the API path, it will always be v1. No matter how the API changes, this version number will not be changed

Having said so many negative textbooks above, the following are some good Web API design patterns I summarized, mainly HTTP RESTful style APIs. If you are using GraphQL or some cloud vendors' SDKs such as AWS Web SDK, Firebase Web SDK and other RPC-like patterns, there are also some for reference.

Naming conventions

  • Use a word or two words that is simple, non-conflicting, non-repetitive, and has a certain pattern or pattern as the name of the project. This naming will be used in multiple places such as the domain name prefix and namespace of the interface. It can also be called "internal code" Or Code name. This link gives many examples of this.
  • Use accurate English (not pinyin, numbers, etc.) nouns to represent the data model.
  • The words used as a data model should be able to accurately describe the meaning of the data model. If it cannot be expressed in accurate words, the development team should have a unified glossary to make an agreement.
  • There is a singular and plural difference between a single data instance and a collection of multiple data. But this kind of thing is best handled by a unified singular and plural library. For example, Rails integrates singular and plural processing by default. In addition, such as pluralize and the like Libraries can do similar things.

Naming style

The style I recommend is database fields, API interface names, field names, etc., using lowercase letters + underscores as a split mode, also called snake_case. The following explains why:

  • The interface name and field name are directly accessible in the URL. Although the URL is case-sensitive, because the URL is related to the domain name, file name, etc., and early browsers are not case-sensitive to the URL, so there is An unwritten convention is that URLs are all lowercase by default, except for certain circumstances (for example, short links use mixed case to ensure that more information is contained with fewer digits).
  • There is no need for hyphens (or minus signs) for segmentation, because data fields are mapped to programming languages, and most of the hyphens in programming languages ​​are keywords, and in most cases they are subtraction operators or symbols that represent negative numbers.
  • Compared with camel case naming, underscore division is convenient for segmentation and merging. Most programming languages ​​have native string segmentation and splicing. In contrast, the operation of camel case naming is more complicated.
  • Camel case naming is very common in Java and JavaScript, but it is not the mainstream style in some other programming languages.

Field Design

Fields can be divided into data instance fields and data model fields. The data instance field scenarios are ID, creation time, modification time, etc.:

  • The name of the ID field is called id instead of pid, photo_id, photoId and the like. Because id is used to determine the uniqueness of the data instance, not a field related to a specific model.
  • Critical time uses create_at and update_at to indicate creation time and modification time. Why not create_time? Because time is ambiguous, it also means "time" in addition to "time".

And the design style of the data model field:

  • Try to use simple, single words as fields instead of obscure and complicated words.
  • Acronyms commonly used in the industry (mainly acronyms, acronyms) such as url, http, etc. can be used as field names. Other abbreviations (mainly abbreviation, that is, word abbreviations) such as desc, auth, cal, func, etc. try to use complete forms to reduce the possibility of ambiguity.
  • The naming of foreign keys or related fields should also be unified. For example, if it is SQL, the foreign key is called user_id, and if NoSQL copies the user instance directly, then the related field should be called user.

Routing Design

My suggestion is to refer to the routing design of Rails. Rails is the originator of the MVC Web back-end framework. Many other language frameworks such as Laravel, Django, Spring, etc. have more or less "learned" from Rails. The following is a table that I have added some content to the design specification of resource-based data routing in the official Rails document:

HTTP VerbPathController#Action
Front-end & Back-endGET/photosphotos#index
Front-end & Back-endGET/photos/:idphotos#show

Why do you want to do this:

  • Make full use of several basic operations of HTTP, and conform to the RESTful style.
  • Create and delete operations are called create/destroy instead of new/delete, because the name of the operation may be in the form of function names in the front and back ends, which avoids the use of new/delete and keywords in some programming languages conflict.
  • You can replace photos with the name of any other resource model, whether it is front-end or back-end, all operation codes can be reused or abstracted directly.
  • Maintain the simplicity of routing for a single resource, and the operations associated with multiple resources can also be designed naturally according to the same idea.
  • Through the agreement on the fixed mode, there is no need to write complicated interface documents. The agreement itself is a document. This is especially useful when the front and back ends are separated and developed by different people.

I will not describe the design of multi-resource associated routing and non-resource routing too much here. You can refer to Active Record Associations and Rails Routing from the Outside In: Non-Resourceful Routes.


A well-designed Web API is not as difficult as imagined. It requires designers to refer to the design specifications of the framework they are using, as well as to refer to the design ideas of popular frameworks. If you encounter a situation that is not in the existing specifications and need to design by yourself, on the one hand, you need to refer to the mainstream frameworks and APIs of mainstream companies, and on the other hand, you must implement "abstraction" and "easy to read" into the design.

Powered by Gatsby. Theme inspired by end2end.

© 2014-2021. Made withby mdluo.