API: Spec - QutEcoacoustics/baw-server GitHub Wiki
The purpose of this specification is to have a public, reliable, non-generated, document that reliably describes the baw-server rest API.
Previous development efforts left the API with redundancy. This spec defines an ideal state the API should strive to achieve.
A full list of available endpoints can be found here at the swagger endpoints for our APIs. For example the staging SwaggerDoc is at https://api.staging.ecosounds.org/api-docs/index.html.
You can also see the Swagger definition at swagger.yaml.
Inspired by: https://speakerdeck.com/jeremiahlee/good-to-great-api-design-patterns-beyond-rest
- All segments of URLs for endpoints should be in
snake_case
- All querystring parameters should be accepted by the server either in
camelCase
orsnake_case
- All JSON responses will have their fields encoded in
snake_case
- All numbers should be encoded bare (as in
123.345
and not"123.345"
) - All dates should be encoded as strings in the ISO8601 format
- Offset or Zulu notation should never be omitted
- Where units are not specified, SI units should be assumed
- Non-SI units are extremely discouraged
- Resources should represent one logical entity
- A base resource should be pluralised (e.g.
audio_events
) - HATEOAS is encouraged
- Chatty API encouraged
- Only the following information should be returned:
- Information directly associated with the resource
- Links to associated resources
- Keys to associated resources
- Exception:
- if only one additional field is needed (other than any relevant keys) it may be included
- Only the following information should be returned:
- Nested resources should be used sparingly
- Only use nested resources for direct and logical associations
- Entities with many associations should not be nested (i.e. no/too many logical parent association[s])
- Similarly: array values are discouraged
- especially where they could hold large numbers of items
- the relationship should instead be expressed as a nested route/sub-entity
- especially where editing the array is possible
- we don't have a reliable method for updating parts of an array
- the only option is to replace the entire value
- the recommended method is to express the collection as a nested route/sub-entity
- especially where they could hold large numbers of items
All API requests should have a standard response format. This includes:
- named
meta
data objects (described in following sections)- must contain at least
status
andmessage
properties.
- must contain at least
- response
data
, either an array or single object ( [...] | {...} )
{
"meta": {
"status": 200,
"message": "OK"
},
"data": []
}
Errors must:
- return an appropriate response code
- return a content type that matches what was requested
APIs may optionally return an 'error details object', which may include links designed to go straight into the page e.g. <a href="{value}">{key}</a>
:
"error": {
"details": "You aren't allowed access, but you can get permission",
"links": {
"sign in": "...",
"request permissions": "...",
"confirm your account": "..."
}
}
Each of the following is implemented by standard on an API endpoint. Exceptions should be denoted.
-
GET
:/resource
- returns many 'resource' objects in an array body
-
GET
:/resource/{key}
- returns a single resource uniquely identified by
key
- returns a single resource uniquely identified by
-
GET
:/resource/new
- returns a single resource with defaults
-
POST
:/resource
- creates a new resource
- the newly created resource is returned
-
PUT
:/resource/{key}
- a resource uniquely identified by
key
is updated - it is expected the entire resource is sent
- the updated resource is returned
- a resource uniquely identified by
-
PATCH
:/resource/{key}
- Updates a subset of the properties uniquely identified by
key
- Updates a subset of the properties uniquely identified by
-
DELETE
:/resource/{key}
- deletes a resource that is uniquely identified by
key
- See API: Archiving for full semantics of soft-deleteable resources
- deletes a resource that is uniquely identified by
See API: Media Types.
Each of the following is optionally implemented on a standard API endpoint.
If you need a resource that supports remote prodcedure calls (RPCs) then consider
a) Redesigning your resource or b) following the pattern in API: Actions document.
NOT IMPLEMENTED
- For any sort of endpoint
- For requests by browsers
- either leave request open
- or present with retry html page
- For API requests
- Return `retry-after` header
- Response should include 'delayed response object`, which may include an indication of high load
"delayed_response": {
"retry_after": 22.0,
"average_response_time": 13.0,
"current_average_response_time": 25.0
}
- for query string parameter:
- `orderBy`=`<field name>`
- `direction`=`[desc|asc]`
- Response should include 'sorting details object'
"sorting": {
"orderBy": "field",
"direction": "desc"
}
- for query string parameters (all optional):
- `page` = `<integer greater than 0>` (default 1)
- `items` = `<integer greater than 0>` (default 25)
- `disable_paging` = `<boolean>` (default `false`, mutually exclusive with `page` and `items`)
- Response should include 'paging details object'
"paging": {
"page": 1,
"items": 25,
"total": 262,
"max_page": 11,
"current": "http:\/\/baw.ecosounds.org\/audio_recordings\/filter?items=25&page=1",
"previous": null,
"next": "http:\/\/baw.ecosounds.org\/audio_recordings\/filter?items=25&page=2"
}
- QSP: `projection_exclude`: comma separated list of resource fields (suggestion, not implemented)
- QSP: `projection_include`: comma separated list of resource fields (suggestion, not implemented)
- Response should include 'projection details object'
"projection": {
"include": [
"(resource field 1)",
"(resource field 2)"
]
}
"projection": {
"exclude": [
"(resource field 1)",
"(resource field 2)"
]
}
- any additional parameters that control a resource are considered an option
- they must not affect filtering, projection, paging, or sorting
- they should affect the shape of the data
- when options are included in a QSP they are not prefixed (e.g.
?bucket_size=86400
) - when options API filter request body they are nested under the
options
key
Currently there is one proposed option: bucket_size
"options": {
"bucket_size": 86400
}
Some routes may need to return summary statisitcs, or aggregates over data. See API: Stats
Capabilities are defined in the API: Capabilties document.
Arbitrary filter functions are defined in the API: Filtering document.