See Repository Service API for full examples of requests and responses. What follows are merely examples of the URL patterns for accessing the service using the HTTP methods GET to read an entity, POST to create an entity, PUT to update an entity, and DELETE to delete an entity.
EULA = end user license agreement
A EULA is yet another entity (node) in the repository service and has the following additional fields:
{ "name": "TCGA Redistribution Use Agreement", "agreement": "The recipient acknowledges that the data herein is provided by TCGA and not SageBionetworks and must abide by ..." } |
The entity kind is 'eula':
POST/GET/PUT/DELETE /repo/v1/eula/# |
Datasets will have a new field called eulaId
which may be null.
There will be a table to record when users agree to EULAs.
The structure of this table will be:
datasetId | datasetVersionId | eulaId | eulaVersionId | userId | agreementDate |
---|
When a user tries to get a location for a dataset or layer:
To create the agreement
POST /repo/v1/agreement { "datasetId":"123", "eulaId":"456" } |
userId
, datasetVersionId
, eulaVersionId
, and agreementDate
will all be set by the system at agreement time. Therefore a user must be authenticated and can only create agreements for himself./repo/v1/query?query=select * from agreement where datasetId=='123' and eulaId='456' and userId='789' |
This work is done.
GET
http://platform.sagebase.org/repo/v1/project/812Response
{ creationDate: 1/1/2011, leaderUserId: 'david.burdick@sagebase.org', numberOfMembers: 1, numberOfPublications: 0, status: 'Active', projectWebsite: 'http://daveproj.com', description: 'project description text' } |
POST
http://platform.sagebase.org/repo/v1/projectTransfer Object
{ leaderUserId: 'david.burdick@sagebase.org', numberOfMembers: 1, numberOfPublications: 0, status: 'Active', projectWebsite: 'http://daveproj.com', description: 'project description text' } |
This is mostly done, except for enforcing authentication and authorization along with the eula.
Get a location, user is not logged in
GET http://platform.sagebase.org/repo/v1/location/511 HTTP/1.1 401 Unauthorized Content-Type: application/json Date: Fri, 11 Feb 2011 19:03:18 GMT Server: Google Frontend Cache-Control: private, x-gzip-ok="" Transfer-Encoding: chunked {"reason":"You must be logged in to access data"} |
Get a location, user has not yet been granted access
GET http://platform.sagebase.org/repo/v1/location/511 HTTP/1.1 403 Forbidden Content-Type: application/json Date: Fri, 11 Feb 2011 19:03:18 GMT Server: Google Frontend Cache-Control: private, x-gzip-ok="" Transfer-Encoding: chunked {"reason":"You are not authorized to access this resource"} |
Get a location, user previously been granted access
GET http://platform.sagebase.org/repo/v1/location/511 HTTP/1.1 200 OK Content-Type: application/json Date: Fri, 11 Feb 2011 19:03:18 GMT Server: Google Frontend Cache-Control: private, x-gzip-ok="" Transfer-Encoding: chunked { "path":"http://data01.sagebase.org.s3.amazonaws.com/tcga_curation_pacakge.tar.gz?AWSAccessKeyId=44CF9SAMPLEF252F707&Expires=1177363698&Signature=vjSAMPLENmGa%2ByT272YEAiv4%3D", "md5sum":"3a4460b6378bea1509954b6c13d84387", "type":"awss3" } |
GET
http://platform.sagebase.org/repo/v1/search?q=aging&type=dataset
JSON Schema Resources
POST /repo/v1/annotationtype { "name":"numberOfSamples", "displayName":"Number of Samples", "schema":{ "description":"The number of samples in a dataset layer.", "type":"integer", "minimum":1 } } |
POST /repo/v1/annotationtype { "name":"status", "displayName":"Status", "schema":{ "description":"The status of a dataset.", "type":"string", "enum":[ "unknown", "pending", "curated", "QCed" ], "default":"unknown" } } |
POST /repo/v1/annotationtype { "name":"curationNotes", "displayName":"Curation Notes", "schema":{ "description":"The free text notes on curation that did not have a proper home in the ISA-Tab representation of the dataset metadata.", "type":"string", "maxLength":4096 } } |
POST /repo/v1/annotationtype { "name":"tissueType", "displayName":"Tissue Type", "schema":{ "description":"The type of tissue in a dataset layer.", "type":"string", "format":"TODO URL to the ontology we are using for this" } } |
POST /repo/v1/annotationtype { "name":"tissueTypes", "displayName":"Tissue Types", "schema":{ "description":"The types of tissue in a dataset.", "type":"array", "items":{ "type":"string", "format":"TODO URL to the ontology we are using for this" } } } |
Ultimately we would like to support a full-on batch implementation similar to https://developers.facebook.com/docs/api/batch/ that would allow fully independent requests to be issued in batch
BATCH REQUEST
curl \ –F 'access_token=…' \ -F 'batch=[ \ { "method": "POST", \ "relative_url": "me/feed", \ "body": "message=Test status update&link=http://developers.facebook.com/" \ }, \ { "method":"GET", \ "relative_url":"me/feed?limit=1" \ } \ ]'\ https://graph.facebook.com |
BATCH RESPONSE
[ { "code": 200, "headers": [ { "name":"Content-Type", "value":"text/javascript; charset=UTF-8"} ], "body":"{\"id\":\"…\"}" }, { "code": 200, "headers": [ { "name":"Content-Type", "value":"text/javascript; charset=UTF-8" }, { "name":"ETag", "value": "…" } ], "body": "{\"data\": [{…}]} } ] |
We have an immediate need for one particular API to support batch requests and in the interest of time could go with something more simple:
BATCH REQUEST
GET /repo/v1/entity/type?batch=123,456,789 |
BATCH RESPONSE
{ "paging": {}, "results": [ { "id":"123", "name":"Example Dataset 1", "type":"/dataset" }, { "id":"456", "name":"Example Dataset 2", "type":"/dataset" }, { "id":"567", "name":"Example Dataset 3", "type":"/dataset" }, ], "totalNumberOfResults": 3 } |
GET /entity/type?batch=123,456,789
GET /entity/acl?batch=123,456,789
Strongly Recommended
Content-Type
and Accept
.If-Match
header for concurrency controlNice To Have
REST is merely guidance on your API. Its not actually a protocol.
Good intro to REST presentation http://www.slideshare.net/guestb2ed5f/scalable-reliable-secure-rest
Spring MVC 3.0 added many more features to make REST-ful services easier to write.
Some REST-ful API Examples
Helpful Links to HTTP protocol Spring stuff:
Google Data Protocol is a REST-ful protocol based upon ATOM and JSON used by many Google APIs
IF-MATCH
header for PUT, PATCH, and DELETE methodsalt=json
alt=json-in-script&callback=myFunction
. OData is a REST-ful protocol based upon ATOM and JSON and backed by Microsoft.
IF-MATCH
header for PUT, MERGE, and DELETE methods$value
at the end of a URL to indicate raw data instead of OData formatted data(proposal from Bruce here)
Some browsers and/or firewalls do not support PUT or DELETE operations. Here are two commons work arounds:
X-HTTP-Method-Override: PUT
X-HTTP-Method-Override: DELETE
_method=PUT
_method=DELETE