APIMAS assumes applications are set up like this:
There is a REST API at a location /<prefix>/api/*
with any static files available at /<prefix>/static/*
This API includes multiple collections of REST resources.
Each resource is defined as a collection of objects of the same type. The object type is defined as a set of fields with a name and type, including field types that refer to fields of other resources.
For each resource collection there are built in operations that accept and return JSON data.
POST /<prefix>/api/<resource>/ data: {key:val...} -> <url>
Creates a new resource in the collection. Its identifier is returned in the form:
/<prefix>/api/<resource>/<id>
The resource is initialized to the fields provided.
GET /<prefix>/api/<resource>/ filter: {}
List the resource collection according to filters, ordering, and pagination input.
PUT /<prefix>/api/<resource/<id> data: {key:val...}
Update (or create) resource with fields from input.
GET /<prefix>/api/<resource>/<id> -> data: {key:val...}
Retrieve a data: {key:val...}
representation of the resource.
DELETE /<prefix>/api/<resource>/<id>
Remove the identified resource from the collection.
GET /<prefix>/api/<resource>/<id>/fields/<field> -> val
Resource fields are accessible recursively by their name
under fields/<field>
.
The value when retrieving is the same
that would be retrieved from the parent resource
under the corresponding field key
({<field>:<value>})
PUT /<prefix>/api/<resource>/<id>/fields/<field> val
Update a field of a resource with a new value.
This value is identical to the one that would be provided
by a PUT on the parent resource under the field key
{<field>:<val>}
[Collection] /<prefix>/api/<resource>/<id>/fields/<field>/*
If a resource field is a collection then all above operations are optionally available recursively.
Resource fields that are themselves collections are not equivalent to top-level resources. They are embedded on their parent resource and are retrieved and set along with the parent. Designers of APIs that need their collections to scale should make them top-level. Nested collections are supported to help data organization and convenience.
Built-in operations can be overridden for customization. The application may also create new named actions:
POST /<prefix>/api/<resource>/<id>/actions/<action> data:{key:val...}
Execute application-provided actions with input.
Each top-level REST resource corresponds to a Data View that connects the API with the data store.
The data view modelling completely defines the REST behaviour of the
API locations. The data view may be linked and triggered in various
interfaces (e.g. GET /search/by-name/<name>/
being equivalent to
GET /resource/<some-id>
). Moreover, the underlying data may have
arbitrary representation in actual storage. The data view is
responsible for connecting the two layers.
The Data Storage layer models the actual representation of data in storage. There should be no native way to store data. The Data View layer should support adapting various storage layers for exposition to the REST API locations. For example, Django models may be one way to model actual storage representation.
The primary responsibility of the application is to hook at the Data View layer and provide storage and business logic. This logic must implement the hooks corresponding to all actions defined in 1.
However, the framework should provide various data store-to-view adapters (e.g. for Django, mongodb, S3). These adapters should themselves automatically hook to all actions defined in 1 and provide further contextualized hooks to applications.
The store-to-view adapter must at least provide these hooks for modelling:
and these hooks for business logic: