139 lines
2.7 KiB
Markdown
139 lines
2.7 KiB
Markdown
# API Guidelines
|
|
|
|
This issue serves to collect our common understanding how to design our API so that it is extensible and usable and understandable.
|
|
|
|
## Resource oriented
|
|
|
|
A resource-oriented API is generally modeled as a resource hierarchy, where each node is either a simple resource or a collection resource. For convenience, they are often called a resource and a collection, respectively.
|
|
|
|
Examples of Resource Nouns:
|
|
|
|
`machine`
|
|
`user`
|
|
`flake`
|
|
|
|
Often resources have sub-resources. Even if it is not foreseen, it is recommended to use plural (trailing `s`) on resources to allow them to be collections of sub-resources.
|
|
|
|
e.g,
|
|
|
|
`users`
|
|
->
|
|
`users/*/profile`
|
|
|
|
## Verbs
|
|
|
|
Verbs should not be part of the URL
|
|
|
|
Bad:
|
|
`/api/create-products`
|
|
|
|
Good:
|
|
`/api/products`
|
|
|
|
Only resources are part of the URL, verbs are described via the HTTP Method.
|
|
|
|
Exception:
|
|
|
|
If a different HTTP Method must be used for technical reasons it is okay to terminate the path with a (short) verb / action.
|
|
|
|
Okay ish:
|
|
`/api/products/create`
|
|
|
|
## Usually the following HTTP Methods exist to interact with a resource
|
|
|
|
- POST (create an order for a resource)
|
|
- GET (retrieve the information)
|
|
- PUT (update and replace information)
|
|
- PATCH (update and modify information) **(Not used yet)**
|
|
- DELETE (delete the item)
|
|
|
|
## Every resource should be CRUD compatible
|
|
|
|
All API resources MUST be designed in a way that allows the typical CRUD operations.
|
|
|
|
Where crud stands for:
|
|
|
|
C - Create
|
|
R - Read
|
|
U - Update
|
|
D - Delete
|
|
|
|
Resources should implement at least a "Read" operation.
|
|
|
|
## Body
|
|
|
|
Use JSON as an exchange format.
|
|
|
|
All responses MUST be JSON parseable.
|
|
|
|
Bad:
|
|
`bare string`
|
|
|
|
Better:
|
|
`"quoted string"`
|
|
|
|
Best: (Enveloped see next section)
|
|
`{ name: "quoted string"}`
|
|
|
|
Errors should have a consistent JSON format, such that it is clear in which field to look at for displaying error messages.
|
|
|
|
## Envelop all Data collections
|
|
|
|
Response data should be wrapped into an JSON Object `{}`
|
|
Lists `[]` should also contain Objects `{}`.
|
|
This allows everything, to be extensible, without breaking backwards compatibility. (Adding fields is trivial, since the schema doesn't change)
|
|
|
|
Example:
|
|
|
|
```
|
|
{
|
|
"users": [{
|
|
first_name: "John",
|
|
last_name: "Doe",
|
|
…
|
|
}, {
|
|
first_name: "Jane",
|
|
last_name: "Doe",
|
|
…
|
|
}
|
|
....
|
|
],
|
|
"skip": 0,
|
|
"limit": 20,
|
|
....
|
|
}
|
|
```
|
|
|
|
Bad Example of a breaking change:
|
|
`GET /api/flakes`
|
|
`old`
|
|
|
|
```
|
|
[
|
|
"dream2nix"
|
|
"disko"
|
|
]
|
|
```
|
|
|
|
`new`
|
|
|
|
```
|
|
[
|
|
{
|
|
name: "dream2nix",
|
|
url: "github/...."
|
|
},
|
|
{
|
|
name: "disko",
|
|
url: "github/...."
|
|
}
|
|
]
|
|
```
|
|
|
|
Those kind of breaking changes can be avoided by using an object from the beginning.
|
|
Even if the object only contains one key, it is extensible, without breaking.
|
|
|
|
## More will follow.
|
|
|
|
...maybe
|