JSON API Documentation
Disclaimer: The API is still under heavy development and breaking changes to endpoints or parameters may be made
If you make anything utilizing our API, please let us know about it - we would love to see!
Except where noted otherwise, all queries require the following header to receive a JSON response:
accept: application/json
Workflow
Add a new Workflow
Note: Due to cwltool run times, the creation of workflows is done asynchronously and an intermediate queue resource is used
POST
/workflows
Parameters
Field | Type | Description |
---|---|---|
url | String | The URL of the repository. Either a gitlab.com or github.com URL, or any Git repository URL. If a gitlab.com or github.com repository URL is used, the following fields will take priority over those parsed from the URL if provided. |
branch | String | The branch of the repository. Required if the URL is not from gitlab.com or github.com. |
path | String | The path within the repository to the workflow file. Required if the URL is not from gitlab.com or github.com. |
packedId | String | The ID of the workflow, to be provided if the workflow file is packed (contains multiple descriptions with $graph ). |
Input
{
"url": "https://github.com/common-workflow-language/workflows/tree/master/workflows/compile/compile1.cwl"
}
{
"url": "https://bitbucket.org/markrobinson96/workflows.git",
"branch": "master",
"path": "/workflows/make-to-cwl/dna.cwl"
}
Success
HTTP/1.1 202 Accepted
Location: /queue/:queueid
Already Exists
HTTP/1.1 303 See Other
Location: /workflows/:URL
Packed Workflow with Multiple Choices
HTTP/1.1 422 Unprocessable Entity
{
"message": "This workflow file is packed and contains multiple workflow descriptions. Please provide a packedId parameter with one of the following values"
"packedId": [
"workflow.cwl",
"main",
"workflow_exome.cwl",
"align.cwl",
"workflow.cwl_2"
]
}
Error
HTTP/1.1 400 Bad Request
Get Workflow Details
GET/workflows/:url
Parameters
Field | Type | Description |
---|---|---|
url | String | Partial URL to the workflow eg "github.com/owner/repo/tree/branch/workflow.cwl" or "bitbucket.org/owner/repo.git/master/workflow.cwl |
Success 200
Field | Type | Description |
---|---|---|
retrievedFrom.repoUrl | String | URL of the Github repository |
retrievedFrom.branch | String | Github branch name or commit ID |
retrievedFrom.path | String | Path to the workflow within the repository |
retrievedFrom.packedId | String | The ID of the workflow within the file, if this is a packed CWL file (contains a document graph). |
retrievedFrom.url | URL | The URL to the page on the site if type is not GENERIC, otherwise the same as repoUrl |
retrievedFrom.rawUrl | URL | The URL directly to the file if type is not GENERIC, otherwise the same as repoUrl |
retrievedFrom.type | Enum | One of GENERIC, GITHUB, GITLAB, BITBUCKET |
retrievedOn | Date | The last time this workflow was updated from the branch |
lastCommit | String | The last commit ID on the branch |
label | String | The label string for the workflow from the CWL description |
doc | String | The doc string for the workflow from the CWL description |
inputs | ||
outputs | ||
steps | ||
dockerLink | String | The URL to dockerhub or "true" if an unrecognised image is used in a docker hint or requirement |
cwltoolVersion | String | The version of cwltool used to parse the workflow |
visualisationDot | String | The DOT source used to generate the visualisation image |
visualisationXdot | URL | A link to the xdot source code for the visualisation image |
visualisationPng | URL | A link to the png format visualisation image |
visualisationSvg | URL | A link to the svg format visualisation image |
robundle | URL | A link to the Research Object Bundle download |
Example URL
/workflows/github.com/common-workflow-language/workflows/tree/master/workflows/lobSTR/lobSTR-workflow.cwl
Example Response
{
"retrievedFrom": {
"repoUrl": "https://github.com/common-workflow-language/workflows.git",
"branch": "master",
"path": "workflows/lobSTR/lobSTR-workflow.cwl",
"url": "https://github.com/common-workflow-language/workflows/blob/master/workflows/lobSTR/lobSTR-workflow.cwl",
"rawUrl": "https://raw.githubusercontent.com/common-workflow-language/workflows/master/workflows/lobSTR/lobSTR-workflow.cwl",
"type": "GITHUB"
},
"retrievedOn": 1502714218616,
"lastCommit": "17b65ea19d81527090fded62ffa0e1ba3b25d561",
"label": "lobSTR-workflow.cwl",
"inputs": {
"reference": {
"type": "File"
},
"rg-sample": {
"type": "String"
},
"p1": {
"type": "ee54066e73d068edfbf9ca5059e14acd"
},
"p2": {
"type": "79ab371b6d0fdbadbf9a4a89ef393353"
},
"output_prefix": {
"type": "String"
},
"rg-lib": {
"type": "String"
},
"strinfo": {
"type": "File"
},
"noise_model": {
"type": "File"
}
},
"outputs": {
"vcf": {
"type": "File"
},
"vcf_stats": {
"type": "File"
},
"bam_stats": {
"type": "File"
},
"bam": {
"type": "File"
}
},
"steps": {
"allelotype": {
"run": "allelotype.cwl",
"runType": "COMMANDLINETOOL",
"sources": {
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#allelotype/bam": {
"sourceIDs": [
"samindex"
]
},
"allelotype": {
"sourceIDs": [
"strinfo"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#allelotype/noise_model": {
"sourceIDs": [
"noise_model"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#allelotype/reference": {
"sourceIDs": [
"reference"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#allelotype/output_prefix": {
"sourceIDs": [
"output_prefix"
]
}
}
},
"samsort": {
"run": "samtools-sort.cwl",
"runType": "COMMANDLINETOOL",
"sources": {
"samsort": {
"sourceIDs": [
"lobSTR"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#samsort/output_name": {
"defaultVal": "\\\"aligned.sorted.bam\\\""
}
}
},
"lobSTR": {
"label": "lobSTR",
"run": "lobSTR-tool.cwl",
"runType": "COMMANDLINETOOL",
"sources": {
"lobSTR": {
"sourceIDs": [
"rg-lib"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#lobSTR/p1": {
"sourceIDs": [
"p1"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#lobSTR/p2": {
"sourceIDs": [
"p2"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#lobSTR/output_prefix": {
"sourceIDs": [
"output_prefix"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#lobSTR/rg-sample": {
"sourceIDs": [
"rg-sample"
]
},
"file:///data/git/3ec0d19076841a1140e71cc3a1b330a56099aac2/workflows/lobSTR/lobSTR-workflow.cwl#lobSTR/reference": {
"sourceIDs": [
"reference"
]
}
}
},
"samindex": {
"run": "samtools-index.cwl",
"runType": "COMMANDLINETOOL",
"sources": {
"samindex": {
"sourceIDs": [
"samsort"
]
}
}
}
},
"dockerLink": "https://hub.docker.com/r/rabix/lobstr",
"cwltoolVersion": "1.0.20170810192106",
"visualisationDot": "digraph workflow {\n graph [\n bgcolor = \"#eeeeee\"\n color = \"black\"\n fontsize = \"10\"\n labeljust = \"left\"\n clusterrank = \"local\"\n ranksep = \"0.22\"\n nodesep = \"0.05\"\n ]\n node [\n fontname = \"Helvetica\"\n fontsize = \"10\"\n fontcolor = \"black\"\n shape = \"record\"\n height = \"0\"\n width = \"0\"\n color = \"black\"\n fillcolor = \"lightgoldenrodyellow\"\n style = \"filled\"\n ];\n edge [\n fontname=\"Helvetica\"\n fontsize=\"8\"\n fontcolor=\"black\"\n color=\"black\"\n arrowsize=\"0.7\"\n ];\n subgraph cluster_inputs {\n rank = \"same\";\n style = \"dashed\";\n label = \"Workflow Inputs\";\n \"p2\" [fillcolor=\"#94DDF4\",label=\"p2\"];\n \"p2\" [fillcolor=\"#94DDF4\",label=\"p2\"];\n \"output_prefix\" [fillcolor=\"#94DDF4\",label=\"output_prefix\"];\n \"reference\" [fillcolor=\"#94DDF4\",label=\"reference\"];\n \"noise_model\" [fillcolor=\"#94DDF4\",label=\"noise_model\"];\n \"strinfo\" [fillcolor=\"#94DDF4\",label=\"strinfo\"];\n \"p1\" [fillcolor=\"#94DDF4\",label=\"p1\"];\n \"p1\" [fillcolor=\"#94DDF4\",label=\"p1\"];\n \"rg-lib\" [fillcolor=\"#94DDF4\",label=\"rg-lib\"];\n \"rg-sample\" [fillcolor=\"#94DDF4\",label=\"rg-sample\"];\n }\n subgraph cluster_outputs {\n rank = \"same\";\n style = \"dashed\";\n labelloc = \"b\";\n label = \"Workflow Outputs\";\n \"bam\" [fillcolor=\"#94DDF4\",label=\"bam\"];\n \"vcf\" [fillcolor=\"#94DDF4\",label=\"vcf\"];\n \"bam_stats\" [fillcolor=\"#94DDF4\",label=\"bam_stats\"];\n \"vcf_stats\" [fillcolor=\"#94DDF4\",label=\"vcf_stats\"];\n }\n \"allelotype\" [label=\"allelotype\"];\n \"samsort\" [label=\"samsort\"];\n \"lobSTR\" [label=\"lobSTR\"];\n \"samindex\" [label=\"samindex\"];\n \"strinfo\" -> \"allelotype\" [label=\"strinfo\"];\n \"reference\" -> \"allelotype\" [label=\"reference\"];\n \"output_prefix\" -> \"allelotype\" [label=\"output_prefix\"];\n \"noise_model\" -> \"allelotype\" [label=\"noise_model\"];\n \"samindex\" -> \"allelotype\" [label=\"bam\"];\n \"lobSTR\" -> \"samsort\" [label=\"input\"];\n \"default1\" -> \"samsort\" [label=\"output_name\"];\n \"default1\" [label=\"\\\"aligned.sorted.bam\\\"\", fillcolor=\"#D5AEFC\"];\n \"rg-lib\" -> \"lobSTR\" [label=\"rg-lib\"];\n \"rg-sample\" -> \"lobSTR\" [label=\"rg-sample\"];\n \"p2\" -> \"lobSTR\" [label=\"p2\"];\n \"p1\" -> \"lobSTR\" [label=\"p1\"];\n \"reference\" -> \"lobSTR\" [label=\"reference\"];\n \"output_prefix\" -> \"lobSTR\" [label=\"output_prefix\"];\n \"samsort\" -> \"samindex\" [label=\"input\"];\n \"samindex\" -> \"bam\";\n \"allelotype\" -> \"vcf\";\n \"lobSTR\" -> \"bam_stats\";\n \"allelotype\" -> \"vcf_stats\";\n}\n",
"visualisationPng": "/graph/png/github.com/common-workflow-language/workflows/blob/master/workflows/lobSTR/lobSTR-workflow.cwl",
"visualisationSvg": "/graph/svg/github.com/common-workflow-language/workflows/blob/master/workflows/lobSTR/lobSTR-workflow.cwl",
"roBundle": "/robundle/github.com/common-workflow-language/workflows/blob/master/workflows/lobSTR/lobSTR-workflow.cwl",
"visualisationXdot": "/graph/xdot/github.com/common-workflow-language/workflows/blob/master/workflows/lobSTR/lobSTR-workflow.cwl"
}
View Workflows
GET/workflows
Parameters
Field | Type | Description |
---|---|---|
search | String | Optional: Limits the workflows received to those containing this string in the label or doc |
page | Integer | The page number to access (0 indexed, defaults to 0) |
size | Integer | The page size requested (defaults to 10) |
Success 200
Field | Type | Description |
---|---|---|
content | List<Workflow> | The workflows returned as per Get Workflow Details |
last | Boolean | Whether this page is the last one |
totalElements | Integer | The total number of workflows |
totalPages | Integer | The total number of pages of this size |
first | Boolean | Whether this page is the first one |
numberOfElements | Integer | The number of workflows on this page |
size | Integer | The page size requested |
number | Integer | The current page number |
Example Response
{
"content": [
{
},
{
}
],
"last": true,
"totalElements": 2,
"totalPages": 1,
"sort": null,
"first": true,
"numberOfElements": 2,
"size": 10,
"number": 0
}
Queue
Check Queue Element
GET/queue/:id
Parameters
Field | Type | Description |
---|---|---|
id | String | The ID of the queue element from the Location header of Add a new Workflow |
Pending 200
Field | Type | Description |
---|---|---|
cwltoolStatus | enum | One of RUNNING, ERROR |
cwltoolVersion | String | The version of cwltool being used to parse the workflow |
message | String | Error message if cwltoolStatus is ERROR |
Example Responses
{
"cwltoolStatus": "RUNNING",
"cwltoolVersion": "1.0.20170622090721",
}
{
"cwltoolStatus": "ERROR",
"cwltoolVersion": "1.0.20170622090721",
"message": "Tool definition failed initialization:\n('https://sparql-test.commonwl.org/schema.rdf', SSLError(SSLError(CertificateError(\"hostname 'sparql-test.commonwl.org' doesn't match either of 'biowardrobe.com', 'demo.biowardrobe.com', 'www.biowardrobe.com'\",),),))\n"
}
Finished 303
HTTP/1.1 303 See Other
Location: /workflows/:url
Examples
Python - Build script for Travis
The API can be utilised as a build step in continuous integration such as in the following example
travis.yml
The python script can be included in the 'script' or 'after_success' areas of travis.yml depending on your usage
language: python
python:
- "2.7"
install:
- pip install requests
script:
- ...
after_success:
- python cwlviewer.py
cwlviewer.py
# Must list 'pip install requests' in travis.yml
import requests
import time
import os
# You can alternatively define these in travis.yml as env vars or arguments
BASE_URL = 'https://view.commonwl.org'
WORKFLOW_PATH = '/workflows/workflow.cwl'
# Travis environment variables
TRAVIS_COMMIT = os.getenv('TRAVIS_COMMIT')
TRAVIS_REPO_SLUG = os.getenv('TRAVIS_REPO_SLUG')
# Whole workflow URL on github
workflowURL = 'https://github.com/' + TRAVIS_REPO_SLUG + '/blob/' + TRAVIS_COMMIT + WORKFLOW_PATH
# Headers
HEADERS = {
'user-agent': 'my-app/0.0.1',
'accept': 'application/json'
}
# Add new workflow with the specific commit ID of this build
addResponse = requests.post(BASE_URL + '/workflows',
data={'url': workflowURL},
headers=HEADERS)
if addResponse.status_code == requests.codes.accepted:
qLocation = addResponse.headers['location']
# Get the queue item until success
qResponse = requests.get(BASE_URL + qLocation,
headers=HEADERS,
allow_redirects=False)
maxAttempts = 5
while qResponse.status_code == requests.codes.ok and qResponse.json()['cwltoolStatus'] == 'RUNNING' and maxAttempts > 0:
time.sleep(5)
qResponse = requests.get(BASE_URL + qLocation,
headers=HEADERS,
allow_redirects=False)
maxAttempts -= 1
if qResponse.headers['location']:
# Success, get the workflow
workflowResponse = requests.get(BASE_URL + qResponse.headers['location'], headers=HEADERS)
if (workflowResponse.status_code == requests.codes.ok):
workflowJson = workflowResponse.json()
# Do what you want with the workflow JSON
# Include details in documentation files etc
print(BASE_URL + workflowJson['visualisationSvg'])
print('Verified with cwltool version ' + workflowJson['cwltoolVersion'])
# etc...
else:
print('Could not get returned workflow')
elif qResponse.json()['cwltoolStatus'] == 'ERROR':
# Cwltool failed to run here
print(qResponse.json()['message'])
elif maxAttempts == 0:
print('Timeout: Cwltool did not finish')
else:
print('Error adding workflow')
SVG sketch of CWL workflow
Note: This method uses a brief YAML
parsing of the standalone CWL file that does not support annotations
like label or doc, and that does not check
for validity or completeness.
POST
/graph/svg
Input
Content-Type: text/yaml
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: Workflow
inputs:
usermessage: string
outputs:
response:
outputSource: step0/response
type: File
steps:
step0:
run:
class: CommandLineTool
inputs:
message:
type: string
inputBinding:
position: 1
baseCommand: echo
outputs:
response:
type: stdout
in:
message: usermessage
out: [response]
Output
Content-Type: image/svg+xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="450pt" height="270pt"
viewBox="0.00 0.00 463.00 278.00" xmlns="http://www.w3.org/2000/svg">
<!-- ... -->
</svg>
Success
HTTP/1.1 200 OK
Content-Type: image/svg+xml
Error
HTTP/1.1 400 Bad Request
PNG sketch of CWL workflow
Note: This method uses a brief YAML
parsing of the standalone CWL file that does not support annotations
like label or doc, and that does not check
for validity or completeness.
POST
/graph/png
Input
Content-Type: text/yaml
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: Workflow
inputs:
usermessage: string
outputs:
response:
outputSource: step0/response
type: File
steps:
step0:
run:
class: CommandLineTool
inputs:
message:
type: string
inputBinding:
position: 1
baseCommand: echo
outputs:
response:
type: stdout
in:
message: usermessage
out: [response]
Output
\x89PNG\n\x1a\n\x00\x00 (binary)
Success
HTTP/1.1 200 OK
Content-Type: image/png
Error
HTTP/1.1 400 Bad Request