NAV Navbar

ThreatSEQ™ Documentation

cURL Requests (python) API Client (python)
  • Introduction
  • Authentication & Authorization
  • Orders
  • Pagination
  • Errors
  • 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.