Skip to content

Low level Sequencescape API

mattdenner edited this page Mar 11, 2011 · 2 revisions

Sequencescape provides a RESTful JSON based API through which client applications can review and manipulate laboratory work requests.

Authentication & Authorisation

Access to resources through the API is governed by two factors:

  • Authentication, which follows the institute's single sign-on policy.
  • Authorisation, which restricts the capabilities provided by the API.

Authorisation is the simplest to deal with: there are only a certain set of applications that need to provide this information, in order to be granted extended functionality, and if you don't know how to do this then your client doesn't need it!

All interactions with the API are being performed on behalf of a user and so their single sign-on information needs to be passed to the API as it would for any other internal application. It must be passed on every request and may govern what capabilities are exposed by the API; in other words, client applications should not rely on two users having the same capabilities from the API (John may be able to create samples, Jane might not) and should not share information between these sessions.

The only URL you need to know (and one that's handy)

The API is designed to be fully RESTful, with each (successful) server response telling the client what it can do from this point (see the Actions below). Therefore client applications only need to know one URL to be able to use the API and that is the root URL. An HTTP GET to this URL will return a JSON block that describes all of the resource types that are available and any actions that are permissible upon these collections as a whole.

For example, the root JSON may be:

{
  "samples": {
    "actions": {
      "read": "http://...../api/1/samples",
      "create": "http://...../api/1/samples"
    }
  }
}

This JSON tells the client that the only resource type available to it is samples. It also tells the client that they can read and create samples (see the Actions section for more information).

There is only one other URL, or rather URL format, that clients can rely on and that is the individual reference to a resource identified by UUID. It is safe for client applications to assume that if they attach the UUID for a resource to the root URL they will be able to perform an HTTP GET to read that resource (assuming they have permission to access the resource). They cannot perform any other action reliably and should make an HTTP GET request to discover exactly what they are permitted to do. Clients can, however, not use this information and obtain the URLs for resources through the API by interrogating it in the appropriate manner.

Actions

All root-level resources exposed through the API include details of the actions that the connect client can perform. There are the four standard actions:

  • The read action is the URL to which an HTTP GET request can be made to read the contents of the resource.
  • update is the URL to which an HTTP PUT, with a JSON body, will perform an update of the resource.
  • create works with an HTTP POST, with a JSON body, creating a new resource.
  • delete will delete the resource if an HTTP DELETE request is made.

Other named actions may be available on individual resources but the semantics of these are described by their documentation, whereas create, read, update and delete are always defined to behave as above.

The actions can be found within an actions element of the JSON. For instance, if the client makes an HTTP GET for a particular sample the JSON would look like this (only relevant elements shown):

{
  "sample": {
    "actions": {
      "read": "http://....../api/1/11111111-2222-3333-4444-555555555555"
    }
  }
}

Here the JSON is telling the client that they are only allowed to read the sample, they can do no other operations upon it.

The hardest thing for users of the API to do is to ignore the structure of the URL associated with an action. When discussing what their application is doing they have a tendency to use the URLs rather than referring to the action by name. This is extremely bad as the contents of these action URLs is not predictable (OK, they are at the moment but their format could change without notice) and so you may believe you can build the appropriate URL by code: don't. Always use the URLs provided in the JSON itself so that the load on the system can be distributed by the server, rather than being tied into the client implementation.

Lists & Pages

When retrieving multiple results, for example when listing all samples, the API will page the results for the client returning a page object. Individual page results contain an actions section that can include any of the following:

  • first is the URL for the first page of results in the set and is always present
  • last is the URL for the last page of results in the set and is always present
  • read is the URL for the current page of results and is always present
  • next is the URL for the next page of results
  • previous is the URL for the previous page of results

For example, a page of samples may have JSON that looks like this (relevant elements only):

{
  "actions": {
    "first": "http://..../api/1/samples/1",
    "last": "http://..../api/1/samples/200",
    "read": "http://..../api/1/samples/10",
    "previous": "http://..../api/1/samples/9",
    "next": "http://..../api/1/samples/11"
  },
  "samples": [
    { ... },
    { ... }
  ]
}

As with any other actions section clients should not rely on the format of the URLs: although it would appear that the example above is for page 10 of 200, it may not be. Instead rely on just the first, last, previous and next to move around.

It is also important to note that the JSON for the individual resources is contained within the samples element in the example above. The elements of that array do not have the normal root element of a solo resource (i.e. in this case they do not have sample) as this information is redundant.

Errors

Error responses from the API server will always contain a JSON body that details what has gone wrong. There are two different types of errors reported in this manner:

If there is an error in relation to the resource itself (as in an invalid value for an attribute) then the response will look like this:

{
  "content": {
    "field1_in_error": [ "error message 1", "error message 2" ],
    "field2_in_error": [ "error message 3" ]
  }
}

Where field1_in_error and field2_in_error are the attributes with invalid values. If the errors are on nested attributes then they will appear in dotted notation, i.e. if the error is on the field bar of the attribute foo then the JSON will contain foo.bar.

With more general errors the response will be:

{
  "general": [ "error message 1", "error message 2" ]
}

Clone this wiki locally