API Conventions

There are a few conventions we follow throughout the API.

Endpoints

The Mira APIs strive to adhere to the REST specification. Suppose there is a Widget resource, then:

  • GET /widgets/ will send back a collection of Widgets the user has access to
  • POST /widgets/ will create a new Widget
  • GET /widgets/{id}/ will fetch a Widget with an identifer equal to id.
    • If the object does not exist, or a user does not have read permissions on that particular Widget, the request will send back a 404 error.
  • PUT /widgets/{id}/ will update a particular Widget - provided the user has write permissions on that object.
  • DELETE /widgets/{id}/ will delete a particular Widget - provided the user has delete permissions on that object.

Additionally, there a few non-REST endpoints that are provided:

  • GET /widgets/count/ will send back the number of Widgets the user has access to.
  • POST /widgets/search/ will perform a search of the Widgets for various parameters.
  • POST /widgets/ids/ will perform a GET of Widgets matching the provided ids in the body of the request.

Responses

Successful collection

{
  "success": true,
  "payload": [
    {
      "id": 0,
      "name": "string",
      "description": "string"
    },
    ...
  ]
}

All responses have a success field. Sucessful responses have this set to true, while errors will always have this set as false. Successful responses have a payload field. When a method is returning a collection this will be a list of items (e.g. GET /widgets/).

Successful Singular

{
  "success": true,
  "payload": {
    "id": 0,
    "name": "string",
    "description": "string"
  }
}

But in the case of a single item (e.g. GET /widgets/2/) this will be an object.

Searches

Most resources have a search endpoint that allows users to list resources sorted by relevance to the specified search parameters. The body of the request may have the following fields specified

Body parameter

{
  "tags": {},
  "include_core": true,
  "query": "string",
  "is_plain": true,
  "filters": {
    "property1": [
      null
    ],
    "property2": [
      null
    ]
  },
  "created_after": "2020-01-28T18:34:01Z",
  "created_before": "2020-01-28T18:34:01Z",
  "updated_after": "2020-01-28T18:34:01Z",
  "updated_before": "2020-01-28T18:34:01Z",
  "page": 0,
  "per_page": 0
}
NameInTypeRequiredDescription
bodybodySearchRequesttruenone
» tagsbodyobjectfalseLimit the results to the specified tags
» include_corebodybooleanfalseWhether or not to include core objects in the results
» querybodystringfalseA text query
» is_plainbodybooleanfalseWhether the query is in plain format or Postgresql ts_query format. Most users should disregard
» filtersbodyobjectfalseA dictionary mapping a property name to a list of acceptable values for that property
» created_afterbodystring(date-time)falseResource created after a certain datetime
» created_beforebodystring(date-time)falseResource created before a certain datetime
» updated_afterbodystring(date-time)falseResource updated after a certain datetime
» updated_beforebodystring(date-time)falseResource updated before a certain datetime
» pagebodyintegerfalsePage number for pagination
» per_pagebodyintegerfalseNumber of results per page

Note that the properties that are acceptable for filtering will vary from resource to resouce. Each resource API will specify the queryable parameters.

Errors

Error response

{
  "success": false,
  "error": {
    "code": 404,
    "message": "Resource not found",
    "type": "error"
  }
}

Errors also follow the same standard response, but instead of a payload field, they have an error object with three fields: code, message, and type.

Here are the errors that you might receive:

StatusMeaningDescription
400Bad RequestRequest was malformed or not validated correctly
401UnauthorizedCould not successful authenticate credentials
403ForbiddenAuthentication was sucessful, but you are not authorized to perform that action
404Not FoundResource not found, or not available to your user
405Method Not AllowedMethod not allowed for that route
500Internal Server ErrorSomething broke in an unexpected way
501Not ImplementedThis method/route is not yet implemented

Generally, 4xx errors occur because of something the client (you) can resolve; 5xx errors are something that the server (us) must resolve.