A Simplified RESTful workflow
Registering Track Hubs
Suppose you've just signed up with the Track Hub Registry. You've also got some remote public track hubs that you want to register with and make available for search on the Registry itself.
After you log in, you can simply register one of your publicly accessible track hubs by POSTing its URL at /api/trackhub. At present, only one hub can be registered at a time. There's a plan to provide bulk request support the registration of multiple data hubs at a time.
Prerequisites
Verify that:
- Your client has successfully logged in and have, as such, obtained a valid authentication token;
- The remote data hub is publicly accessible and is compliant with UCSC Track Hubs specification.
Procedure
- Make a POST request to the /api/trackhub endpoint that includes a User header with your username and an Authorization: Token header with the given authentication token;
- Examine the response. The response code indicates whether the request succeeded, or how it failed;
- A successful request returns an array of JSON objects, where each object is a translation of the configuration of a trackDb belonging to the track hub.
Example: registration request and response
In this example, we are going to register the CSHL Biology of Genomes meeting 2013 demonstration assembly hub. For this, we are obviously assuming we are those who have published this data and are in control of it. The Registry does not make any effort to check this kind of information: you are responsible for your own actions which will be eventually visible by everyone on the Registry itself.
Any request to the Registration API must supply the user's credentials with the following headers:
User: [username] Authorization: Token [valid token]
The POST /api/trackhub message must contain the URL of remote public hub (can specify the URL of the hub.txt as well), a map from assembly names as specified in the hub to INSDC accessions (in case of assemblies not supported by UCSC, see genome assembly support), and, optionally, the type of the assembly data contained in the hub, which can be one of "genomics", "epigenomics", "transcriptomics", "proteomics" (default: "genomics"). By specifying the type you allow the user to search for track hubs based on particular types. The hub in this example is an assembly hub so we're also posting a map of hub assembly names to their respective INSDC accessions. Also, we implicitly specify that the hub contains genomics data.
Request:
POST https://trackhubregistry.org/api/trackhub User: exampleuser Authorization: Token 6l5/GuIiOSCywuSI9HF1VU97clwb/CXPDFS0MyAB/HCZuxtjQBj4uORZL8NY3Yhi { "url": "http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt", "assemblies": { "araTha1": 'GCA_000001735.1', "ricCom1": 'GCA_000151685.2', "braRap1": 'GCA_000309985.1' } }The above request can be done via the clients (see Example clients section).
Some things happen in the background once you've made the request. Most notably, the server runs the hubCheck from UCSC to check that the files in the hub are correctly formatted. The Registry will ignore error messages related to the use of deprecated features. For any other error, the request will be deemed unsuccessful and the response body will report the hubCheck output report.
See what can possibly go wrong for a comprehensive list of possible errors.
If the request is successful, the response body is an array of JSON objects, one for each configuration of assembly trackDbs belonging to the hub. These are the objects created and stored in the Registry and the ones the user will be able to search on. All trackDb objects specify the same 'hub' property. This allows the Registry to group trackDb documents of different assemblies according to a particular hub. The response header Location reports their respective URIs in the same order, which can be used to request individual operations on a single trackDb registry entity with the GET|PUT|DELETE /api/trackdb endopoints.
In our example, the CSHL Biology of Genomes meeting 2013 demonstration assembly hub contains data for three assemblies (araTha1, ricCom1, braRap1), so the response body is an array of three trackDb objects, one for each of these assemblies.
Response:
201 Created Content-type: application/json; charset=utf-8 Location: [ 'https://trackhubregistry.org/api/trackdb/KRBr5PS7RmapaFr7ofpTBA, 'https://trackhubregistry.org/api/trackdb/hB8Npdm1ST2gBwkbQThkVg', 'https://trackhubregistry.org/api/trackdb/FOEM87nETMOCOglmm0sSsg' ] ... [ { // ricCom1 trackDb configuration 'owner': 'exampleuser', 'source': { 'checksum': 'f9561ae6f7883add3698fad7abab7e13', 'url': 'http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/ricCom1/trackDb.txt' }, 'hub': { 'shortLabel': 'Plants', 'name': 'cshl2013', 'url': 'http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt', 'longLabel': 'CSHL Biology of Genomes meeting 2013 demonstration assembly hub' }, 'species': { 'scientific_name': 'Ricinus communis', 'common_name': 'castor bean', 'tax_id': '3988' }, 'assembly': { 'synonyms': 'ricCom1', 'name': 'JCVI_RCG_1.1', 'accession': 'GCA_000151685.2' }, 'configuration': { 'repeatMasker_': { 'priority': '149.1', 'visibility': 'dense', 'compositeTrack': 'on', 'track': 'repeatMasker_', 'shortLabel': 'RepeatMasker', } ... } ... }, { // araTha1 trackDb configuration ... 'hub': { 'shortLabel': 'Plants', 'name': 'cshl2013', 'url': 'http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt', 'longLabel': 'CSHL Biology of Genomes meeting 2013 demonstration assembly hub' }, ... }, { // braRap1 trackDb configuration ... 'hub': { 'shortLabel': 'Plants', 'name': 'cshl2013', 'url': 'http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt', 'longLabel': 'CSHL Biology of Genomes meeting 2013 demonstration assembly hub' }, ... } ]The response body contains the array of three trackDb configuration objects, the first referring the ricCom1 assembly and the other two to araTha1 and braRap1, respectively. The header Location contains the list of the corresponding URIs in the same order as the response body array. As can be seen, all three assemblies refer to the same hub.
What can possibly go wrong
Remember: always check the response code since it indicates whether the request succeeded, or how it failed.
- if the request is successful, the server returns HTTP response code 201 (Created)
- if the credentials supplied in the authentication header are invalid, the server returns HTTP response code 401
- if your hub is not compliant with the UCSC hub specs, the server returns HTTP response code 400. The body contains the message: "hubCheck report: ..."
- if the hub is not available or cannot be correctly parsed, the server returns HTTP response code 400. The response body message contains the error
- your hub genome subdirectory names must be valid UCSC DB names (assembly synonyms, e.g. hg38) or you must provide a map from these names to their corresponding INSDC accessions (i.e. assembly accession + version, e.g. GCA_000001405.1). If neither of the two conditions are met, the server returns HTTP response code 400 with the message "Unable to find a valid INSDC accession for genome assembly [..]"
- if one of the hub trackDb configurations cannot be translated to valid JSON, the server returns HTTP response code 400. The body contains the message "Failed: ..." with an output describing the reasons why validation failed
- if the Registry encountered an unexpected condition which prevented it from fulfilling the request, it returns HTTP response code 500
- if the Registry is currently unable to handle the request due to a temporary overloading or maintenance, it returns HTTP response code 503
Example Clients
#!/usr/bin/perl use strict; use warnings; use JSON; use LWP::UserAgent; my $SERVER = 'https://trackhubregistry.org'; # Change these variables my $HUB_URL = 'http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt'; my $USER = 'username'; my $PASSWORD = 'password'; # Provide assemblies mapping (Only if needed) my %ASSEMBLIES_MAPPING = ( 'araTha1' => 'GCA_000001735.1', 'ricCom1' => 'GCA_000151685.2', 'braRap1' => 'GCA_000309985.1' ); sub login { my ($server) = @_; my $ua = LWP::UserAgent->new; my $res = $ua->post( "$server/api/login", 'Content-Type' => 'application/json', Content => to_json({ username => $USER, password => $PASSWORD }) ); if (!$res->is_success) { print "Couldn't login, reason: ", $res->content, " [", $res->code, "]\n"; exit; } my $json_response = from_json($res->content); my $auth_token = $json_response->{'auth_token'}; print "Logged in [$auth_token]\n"; return $auth_token; } sub logout { my ($server, $headers) = @_; my $ua = LWP::UserAgent->new; my $res = $ua->post("$server/api/logout", %$headers); if (!$res->is_success) { print "Couldn't logout, reason: ", $res->content, " [", $res->code, "]\n"; exit; } print "Logged out\n"; } sub register_trackhub { my ($server, $hub_url, $headers) = @_; my $ua = LWP::UserAgent->new; my $res = $ua->post( "$server/api/trackhub", 'Content-Type' => 'application/json', Content => to_json({ url => $hub_url, assemblies => \%ASSEMBLIES_MAPPING }), %$headers ); if (!$res->is_success) { print "Couldn't register track hub at $hub_url, reason: ", $res->content, " [", $res->code, "]\n"; exit; } print "I have registered hub at $hub_url\n"; } my $auth_token = login($SERVER); my %headers = ( 'user' => $USER, 'Authorization' => "Token $auth_token" ); register_trackhub($SERVER, $HUB_URL, \%headers); logout($SERVER, \%headers);