Introduction
Welcome to the ThreatSeq™ API! You can use this API to submit sequences for processing and to check the progress and status of previously submitted orders.
We have language bindings in Python and examples using cURL from the shell. You can view code examples in the dark area to the right, and you can switch the platform of the examples with the tabs in the top right.
You can download the Python client here.
Authentication & Authorization
To authorize, use this code:
from json import dumps
import requests as r
resp = r.post("https://app.threatseq.org/api/auth",
data=dumps({"name": "yourname@example.org", "key": "*YOUR API KEY HERE*"}),
headers={"content-type": "application/json"})
print(resp.json())
from threatseq import ThreatSEQClient
c = ThreatSEQClient()
c.authenticate("yourname@example.org", "*YOUR API KEY HERE*")
# can now call other authenticated methods on client instance...
curl \
-d '{"name": "yourname@example.org", "key": "*YOUR API KEY HERE*"} ' \
-H "Content-Type: application/json" \
-X POST \
https://app.threatseq.org/api/auth
The above command returns JSON structured like this:
{
"access_token": "*AUTHENTICATION-TOKEN*"
}
ThreatSeq™ uses API keys to allow access to the API.
ThreatSeq™ expects the API access key to be included in all API requests to the server in a header that looks like the following:
Authorization: JWT *AUTHENTICATION-TOKEN*
Orders
Submit sequences to create an order
from json import dumps
import requests as r
resp = r.post("https://app.threatseq.org/api/auth",
data=dumps({"name": "yourname@example.org", "key": "*YOUR API KEY HERE*"}),
headers={"content-type": "application/json"})
auth = resp.json()
with open("samples.fa", "r") as f:
resp = r.post("https://app.threatseq.org/ext/orders",
data=dumps({"name": "Test Order", "content": f.read()}),
headers={
"Content-Type": "application/json",
"Authorization": "JWT {}".format(auth['access_token'])
})
print(resp.json())
from threatseq import ThreatSEQClient
c = ThreatSEQClient()
c.authenticate("yourname@example.org", "*YOUR API KEY HERE*")
with open("samples.fa", "r") as f:
print(c.create_order("Test Order", f.read()))
curl \
-d '{"name": "Test Order", "content": "*FASTA-DATA*"} ' \
-H "Content-Type: application/json" \
-H "Authorization: JWT *AUTHENTICATION-TOKEN*" \
-X POST \
https://app.threatseq.org/api/ext/orders
The above command returns JSON structured like this:
{
"data": {
"group_id": 1,
"id": 1,
"in_progress": true,
"name": "Test Order",
"sequence_count": 0,
"submitted": 1518915733.433546,
"threat_level": null
}
}
This endpoint creates an order.
HTTP Request
POST https://app.threatseq.org/api/ext/orders
POST Parameters
| Parameter | Default | Description |
|---|---|---|
| name | empty | Searchable name of the order (string) (optional) |
| content | (none) | FASTA data containing sequences. (string) (required) |
| type | nucleotide | Type of sequences in this order. (string, "nucleotide" OR "amino acid") (optional) |
| dryrun | False | Create orders but do not run them. For testing purposes. (boolean) (optional) |
Response data Key Descriptions
| Response Key | Description |
|---|---|
| group_id | The group ID of the submitting user group |
| id | The ID of the newly created order |
| in_progress | a boolean indicating whether the order is still in progress |
| name | The searchable name of the submitted order |
| sequence_count | The number of sequences generated by this order. Will start as 0 until the order is processed for analysis. |
| submitted | Timestamp of the submission |
| threat_level | The calculated threat level of the order. Will be null until the order is complete. The threat levels are detailed below. |
Order/Sequence Threat Levels
| Value | Threat Level | Description |
|---|---|---|
| 0 | In progress | Threat detection is still running. |
| 1 | Non-threat | Matches a sequence in a non-select agent's genome. |
| 2 | Tier 4 | At least one 200bp segment had a best match alignment to a select agent's genome. |
| 3 | Tier 3 | Matches a non-concerning sequence in an annotated select agent's genome. |
| 4 | Tier 2 | Matches any sequence in a non-annotated select agent's genome. |
| 5 | Tier 1 | Matches a known sequence of concern or Tier 1 virus. |
| -1 | Below detection limit | Sequence is less than 200bp. |
| -2 | Unidentified | Sequence could not be found in any database. |
| -3 | Not processed | Threat detection skipped due to the dryrun flag. |
Get a list of orders
from json import dumps
import requests as r
resp = r.post("https://app.threatseq.org/api/auth",
data=dumps({"name": "yourname@example.org", "key": "*YOUR API KEY HERE*"}),
headers={"content-type": "application/json"})
auth = resp.json()
resp = r.get("https://app.threatseq.org/api/ext/orders",
headers={
"Content-Type": "application/json",
"Authorization": "JWT {}".format(auth['access_token'])
})
print(resp.json())
from threatseq import ThreatSEQClient
c = ThreatSEQClient()
c.authenticate("yourname@example.org", "*YOUR API KEY HERE*")
print(c.get_orders(1))
curl \
-H "Content-Type: application/json" \
-H "Authorization: JWT *AUTHENTICATION-TOKEN*" \
https://app.threatseq.org/api/ext/orders
The above command returns JSON structured like this:
{
"data": [
{
"group_id": 1,
"id": 1,
"in_progress": false,
"name": "Test Order",
"sequence_count": 1,
"submitted": 1518915733.433546,
"threat_level": 0
}
],
"nextPage": "",
"perPage": "",
"total": "",
"totalPages": ""
}
This endpoint retrieves all orders.
HTTP Request
GET https://app.threatseq.org/api/ext/orders
GET https://app.threatseq.org/api/ext/orders?q=Test
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| q | empty | When passed a string, will return orders with that string in the name. |
See above for descriptions of the data keys and threat levels.
See below for details regarding the use of pagination.
Get details for an order
from json import dumps
import requests as r
resp = r.post("https://app.threatseq.org/api/auth",
data=dumps({"name": "yourname@example.org", "key": "*YOUR API KEY HERE*"}),
headers={"content-type": "application/json"})
auth = resp.json()
resp = r.get("https://app.threatseq.org/api/ext/orders/1",
headers={
"Content-Type": "application/json",
"Authorization": "JWT {}".format(auth['access_token'])
})
print(resp.json())
from threatseq import ThreatSEQClient
c = ThreatSEQClient()
c.authenticate("yourname@example.org", "*YOUR API KEY HERE*")
print(c.get_order(1))
curl \
-H "Content-Type: application/json" \
-H "Authorization: JWT *AUTHENTICATION-TOKEN*" \
https://app.threatseq.org/api/ext/orders/1
The above command returns JSON structured like this:
{
"data": {
"group_id": 1,
"id": 1,
"in_progress": false,
"name": "Test Order",
"sequence_count": 1,
"submitted": 1518915733.433546,
"threat_level": 0
}
}
This endpoint retrieves details for an order.
HTTP Request
GET https://app.threatseq.org/api/ext/orders/<order_id>
URL Parameters
| Parameter | Description |
|---|---|
| order_id | The ID of the order to retrieve |
See above for descriptions of the data keys and threat levels.
Get sequences for an order
from json import dumps
import requests as r
resp = r.post("https://app.threatseq.org/api/auth",
data=dumps({"name": "yourname@example.org", "key": "*YOUR API KEY HERE*"}),
headers={"content-type": "application/json"})
auth = resp.json()
resp = r.get("https://app.threatseq.org/api/ext/orders/1/sequences",
headers={
"Content-Type": "application/json",
"Authorization": "JWT {}".format(auth['access_token'])
})
print(resp.json())
from threatseq import ThreatSEQClient
c = ThreatSEQClient()
c.authenticate("yourname@example.org", "*YOUR API KEY HERE*")
print(c.get_sequences(1))
curl \
-H "Content-Type: application/json" \
-H "Authorization: JWT *AUTHENTICATION-TOKEN*" \
https://app.threatseq.org/api/ext/orders/1/sequences
The above command returns JSON structured like this:
{
"data": [
{
"header": "B._anthracis_VF|red",
"id": 1,
"index": 0,
"order_id": 1,
"length": 600,
"status": 0
},
{
"header": "B._anthracis_non-VF|yellow-green",
"id": 2,
"index": 1,
"order_id": 1,
"length": 600,
"status": 0
}
],
"nextPage": "",
"perPage": "",
"total": "",
"totalPages": ""
}
This endpoint retrieves sequences for an order.
HTTP Request
GET https://app.threatseq.org/api/ext/orders/<order_id>/sequences
GET https://app.threatseq.org/api/ext/orders/<order_id>/sequences?filters=2&filters=1
URL Parameters
| Parameter | Description |
|---|---|
| order_id | The ID of the order for which to retrieve sequences |
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| filters | (none) | Limits results to sequences that have a threat status matching values passed via filters arguments. |
See above for descriptions of the threat levels, i.e. the status key.
See below for details regarding the use of pagination.
Get details for a sequence
from json import dumps
import requests as r
resp = r.post("https://app.threatseq.org/api/auth",
data=dumps({"name": "yourname@example.org", "key": "*YOUR API KEY HERE*"}),
headers={"content-type": "application/json"})
auth = resp.json()
resp = r.get("https://app.threatseq.org/api/ext/orders/1/sequences/1",
headers={
"Content-Type": "application/json",
"Authorization": "JWT {}".format(auth['access_token'])
})
print(resp.json())
from threatseq import ThreatSEQClient
c = ThreatSEQClient()
c.authenticate("yourname@example.org", "*YOUR API KEY HERE*")
print(c.get_sequence(1, 1))
curl \
-H "Content-Type: application/json" \
-H "Authorization: JWT *AUTHENTICATION-TOKEN*" \
https://app.threatseq.org/api/ext/orders/1/sequences/1
The above command returns JSON structured like this:
{
"data": {
"dbs": ["nr"],
"reports": [
{
"db": "nr",
"matched": [
{
"accession": "AAD17218.1",
"align_length": 1217,
"bit_score": 843.2,
"e_value": 2e-241,
"gap_openings": 0,
"mismatches": 0,
"organism": "Influenza A virus (A/Brevig Mission/1/1918(H1N1))",
"orientation": 1,
"percent_query_length": 99.91789819376027,
"percent_subject_length": 99.75369458128078,
"pident": 100,
"protein": "hemagglutinin, partial [Influenza A virus (A/Brevig Mission/1/1918(H1N1))]",
"q_end": 1218,
"q_frame": 1,
"q_start": 1,
"s_end": 406,
"s_len": 1218,
"s_start": 1,
"startswith_start_codon": true,
"taxid": 88776
},
{
"accession": "ABH07372.1.1",
"align_length": 1217,
"bit_score": 836.6,
"e_value": 2e-239,
"gap_openings": 0,
"mismatches": 2,
"organism": "synthetic construct",
"orientation": 1,
"percent_query_length": 99.91789819376027,
"percent_subject_length": 71.5547703180212,
"pident": 99.01477832512316,
"protein": "hemagglutinin, deltaCS [synthetic construct]",
"q_end": 1218,
"q_frame": 1,
"q_start": 1,
"s_end": 406,
"s_len": 1218,
"s_start": 1,
"startswith_start_codon": true,
"taxid": 32630
}
],
"method": "postmatch",
"name": "battelle",
"result": true
}
],
"triggers": [
{
"threat_level": 3,
"accessions": [
"AAD17218.1"
]
},
{
"threat_level": 2,
"accessions": [
"AAD17218.1"
]
}
],
"soc_metadata_url": "https://app.threatseq.org/sequence_browser/*UUID*?access_token=*ACCESS_TOKEN*"
}
}
This endpoint provides details for a sequence.
HTTP Request
GET https://app.threatseq.org/api/ext/orders/<order_id>/sequences/<seq_id>
URL Parameters
| Parameter | Description |
|---|---|
| order_id | The ID of the order to which the sequence belongs |
| seq_id | The ID of the sequence to retrieve |
Response data Key Descriptions
| Response Key | Description |
|---|---|
| dbs | List of databases against which the sequence will be run ('nr' only) |
| reports | List of results per database and algorithm/method |
| triggers | List of detected threat levels and causes |
| soc_metadata_url | Link to standalone sequence browser to be linked externally or loaded in an iframe |
Response data.reports Key Descriptions
| Response Key | Description |
|---|---|
| db | The database against which the sequence was matched |
| matched | Parsed m8 spec data pertaining to the database results |
| method | Reporting algorithm - postmatch |
| name | Reporting name - battelle |
| result | Reporting result - true/false |
Response data.triggers Key Descriptions
While a sequence is assigned a single threat level, it can meet the criteria for multiple levels - all matching levels (except Tier 1) are returned in the triggers section.
See above for descriptions of the threat_level values.
| Response Key | Description |
|---|---|
| threat_level | A threat level triggered by the sequence |
| accessions | A list of accessions from the 'nr' database meeting the criteria for the given threat level |
Pagination
Several of the endpoints above support pagination, though results are not paginated by default, that is, if pagination arguments are not used when requesting an endpoint, all the results are returned and the pagination response keys will be empty.
Paginated results can be requested by providing one or two arguments to the request, e.g.:
GET http://threatseq.org/api/ext/orders?page=1&per_page=50
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| page | (none) | The requested page number |
| per_page or perPage | (none) | The number of items to return per page |
Pagination response keys
| Key | Description |
|---|---|
| nextPage | The page number of the next page, if available. |
| perPage | The number of items being returned per page. |
| total | The total number of items available for request. |
| totalPages | The total number of pages available for request. |
Errors
The ThreatSeq™ API uses the following error codes:
| Error Code | Meaning |
|---|---|
| 400 | Bad Request -- Your request is invalid. |
| 401 | Unauthorized -- Your API key is wrong or missing. |
| 403 | Forbidden -- The resource requested belongs to another user. |
| 404 | Not Found -- The specified resource could not be found. |
| 405 | Method Not Allowed -- You tried to access a resource with an invalid method. |
| 406 | Not Acceptable -- You requested a format that isn't json. |
| 410 | Gone -- The resource requested has been removed from our servers. |
| 429 | Too Many Requests -- You're requesting too many resource! Slow down! |
| 500 | Internal Server Error -- We had an internal problem with our server. Try again later or contact us if it persists. |
| 503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |