Skip to content
This repository has been archived by the owner on Jan 25, 2023. It is now read-only.

Update BeaconError documentation (issue #262) #267

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 171 additions & 68 deletions beacon.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

# Beacon API Specification v1.0.0
# Beacon API Specification v1.1.1

Beacon is a web service for genetic data sharing. Beacon permits simple queries regarding the presence or absence of a specified variant in a given dataset. This is the key idea behind Beacon, by allowing these queries Beacon makes the data discoverable. If the user finds their variant(s) of interest, Beacon will point them to the appropriate place to gain access to the data (e.g. the European Genome-Phenome Archive, EGA).

Expand Down Expand Up @@ -44,31 +44,128 @@ Both granting access to the data and identifying `bona-fide researchers` **is no

### Errors

The server MUST respond with the appropriate HTTP status code when an error condition is detected. In the case of transient
server errors, (e.g., 500 and other 5xx status codes), the client SHOULD implement appropriate retry logic.
The server MUST respond with the appropriate HTTP status code when an error condition is detected. In the case of transient server errors, (e.g., 500 and other 5xx status codes), the client SHOULD implement appropriate retry logic.

For errors that are specific to the Beacon API, the response will be one of the HTTP status codes represented in the table below.
The response body SHOULD be a JSON object (`Content-Type: application/json`) providing machine-readable information
about the nature of the error, along with a human-readable description.
For errors which are specific to the Beacon API, they will be encoded in the `error` field of either `BeaconAlleleResponse` or `BeaconDatasetAlleleResponse`, depending on the scope of the error.
The response body SHOULD be a JSON object (`Content-Type: application/json`) providing machine-readable information about the nature of the error, along with a human-readable description.

#### Example 1
* Query
`/query?assemblyId=GRCh38&start=1111&referenceName=1&referenceBases=A&alternateBases=C`
* Response
```json
[
{
"beaconId": "some-beacon",
"apiVersion": "v1.1.1",
"exists": null,
"alleleRequest": {
"referenceName": "1",
"start": 1111,
"end": null,
"startMin": null,
"startMax": null,
"endMin": null,
"endMax": null,
"referenceBases": "A",
"alternateBases": "C",
"variantType": null,
"assemblyId": "GRCh38",
"datasetIds": null,
"includeDatasetResponses": "null"
},
"datasetAlleleResponses": null,
"error": {
"errorCode": "400",
"errorMessage": "User provided assemblyId (GRCh38) does not match with dataset assembly (GRCh37)"
}
}
]
```
which means that at least one of the datasets in this Beacon has a different assembly (GRCh37 in this example).

The following error types are defined:
#### Example 2
* Query
`/query?assemblyId=GRCh38&start=1111&referenceName=1&referenceBases=A&alternateBases=C&includeDatasetResponses=ALL`
* Response
```json
[
{
"beaconId": "some-beacon",
"apiVersion": "v1.1.1",
"exists": true,
"alleleRequest": {
"referenceName": "1",
"start": 1111,
"end": null,
"startMin": null,
"startMax": null,
"endMin": null,
"endMax": null,
"referenceBases": "A",
"alternateBases": "C",
"variantType": null,
"assemblyId": "GRCh38",
"datasetIds": [
"1","2"
],
"includeDatasetResponses": "ALL"
},
"datasetAlleleResponses": [
{
"datasetId": "1",
"exists": true,
"error": null,
"frequency": 0.002222,
"variantCount": 1,
"callCount": 4,
"sampleCount": 1,
"note": null,
"externalUrl": null,
"info": null
},
{
"datasetId": "2",
"exists": null,
"error": {
"errorCode": "400",
"errorMessage": "User provided assemblyId (GRCh38) does not match with dataset assembly (GRCh37)"
},
"frequency": null,
"variantCount": null,
"callCount": null,
"sampleCount": null,
"note": null,
"externalUrl": null,
"info": null
}
],
"error": {
"errorCode": 200
}
}
]
```
which means that dataset 2 has a different assembly but the Beacon can return the information regarding the other dataset. Notice that the top `error` field is not empty either and contains `"errorCode" : 200`.

The following error types are defined:

| Error type | HTTP status code | Description |
|---|:---:|---|
|Bad request|400|Mandatory parameters are missing or they are invalid|
|Unauthorized|401|An unauthenticated user is trying to access a protected resource|
|Forbidden|403|The resource is protected for all users, or the user is authenticated but they are not granted access for this resource|

The error type SHOULD be chosen from this table and be accompanied by the specified HTTP status code.
An example of a valid JSON error response is:
The error type SHOULD be chosen from this table.

If there is no error, the `errorCode` will be `200`.
```json
"error": {
"errorCode": 400,
"errorMessage": "Missing mandatory parameter referenceName"
}
```
"errorCode": 200
}
```

Notice that the server MUST always fill the `error` field, although `null` is also accepted for backward compatibility.

### CORS
Beacon API SHOULD support cross-origin resource sharing (CORS) and follow [GA4GH CORS recommendations](https://docs.google.com/document/d/1Ifiik9afTO-CEpWGKEZ5TlixQ6tiKcvug4XLd9GNcqo/edit).
Expand All @@ -95,7 +192,7 @@ Beacon API SHOULD support cross-origin resource sharing (CORS) and follow [GA4GH
|---|---|:---:|---|
|*id* *|Unique identifier of the beacon. Use reverse domain name notation.|string|org.ga4gh.beacon|
|*name* *|Human readable name of the beacon|string|EGA Beacon|
|*apiVersion* *|Version of the API provided by the beacon.|string|v1.0.0|
|*apiVersion* *|Version of the API provided by the beacon.|string|v1.1.1|
|*organisation* *|Organisation providing the Beacon|object|Beacon Organisation object (see below)|
|*datasets* *|Datasets served by the beacon. Any beacon should specify at least one dataset.|array|Array of Beacon Dataset objects (see below)|
|description|Description of the beacon.|string|"This sample set comprises cases of schizophrenia with additional cognitive measurements, collected in Aberdeen, Scotland."|
Expand Down Expand Up @@ -175,7 +272,7 @@ An example `GET` request and response to the info endpoint:
<
{
"alternativeUrl": "https://ega-archive.org/beacon_web/",
"apiVersion": "0.4",
"apiVersion": "1.1.1",
"createDateTime": "2015-06-15T00:00.000Z",
"dataset": [
{
Expand All @@ -188,7 +285,7 @@ An example `GET` request and response to the info endpoint:
"variantCount": 74,
}
],
"description": "This <a href=\"http://ga4gh.org/#/beacon\">Beacon</a> is based on the GA4GH Beacon <a href=\"https://github.com/ga4gh/beacon-team/blob/develop/src/main/resources/avro/beacon.avdl\">API 0.4</a>",
"description" : "This <a href=\"https://beacon-project.io/\">Beacon</a> is based on the GA4GH Beacon <a href=\"https://raw.githubusercontent.com/ga4gh-beacon/specification/v1.1.1/beacon.yaml\"></a>",
"id": "ega-beacon",
"info": {
"size": "60270153"
Expand Down Expand Up @@ -236,7 +333,7 @@ An example `GET` request and response to the info endpoint:
"start": 866510
}
],
"version": "v04",
"version": "v1.1.1",
"welcomeUrl": "https://ega-archive.org/beacon_web/"
}
* Closing connection 0
Expand Down Expand Up @@ -304,9 +401,9 @@ An example `GET` request and response to the info endpoint:

Example of how to use the GET method in the `/query` endpoint:

curl -v 'https://localhost:5000/query?referenceName=1&start=0&end=0&startMin=28000000&startMax=29000000&endMin=28000000&endMax=29000000&referenceBases=A&alternateBases=T&assemblyId=GRCh37&datasetIds=EGAD00000000028&includeDatasetResponses=ALL'
######
`curl -v 'https://localhost:5000/query?referenceName=1&start=0&end=0&startMin=28000000&startMax=29000000&endMin=28000000&endMax=29000000&referenceBases=A&alternateBases=T&assemblyId=GRCh37&datasetIds=EGAD00000000028&includeDatasetResponses=ALL'`

```
> GET /query?referenceName=1&start=0&end=0&startMin=28000000&startMax=29000000&endMin=28000000&endMax=29000000&referenceBases=A&alternateBases=T&assemblyId=GRCh37&datasetIds=EGAD00000000028&includeDatasetResponses=ALL HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
Expand All @@ -317,13 +414,15 @@ Example of how to use the GET method in the `/query` endpoint:
< Content-Type: application/json
< Content-Length: 1078
< Server: Werkzeug/0.14.1 Python/3.6.5
< Date: Mon, 11 Jun 2018 07:29:26 GMT
< Date: Wed, 30 Jan 2018 07:29:26 GMT
<
{
"beaconId": "ega-beacon",
"apiVersion": "0.4",
"apiVersion": "1.1.1",
"exists": true,
"error": null,
"error": {
"errorCode": 200
},
"alleleRequest": {
"referenceName": "1",
"start": 0,
Expand Down Expand Up @@ -351,18 +450,20 @@ Example of how to use the GET method in the `/query` endpoint:
"note": "This sample set comprises cases of schizophrenia with additional cognitive measurements, collected in Aberdeen, Scotland.",
"externalUrl": null,
"info": {},
"error": null
"error": {
"errorCode": 200
}
}
]
}
* Closing connection 0
######
Example of how to use the POST method in the "/query" path:
```

Example of how to use the POST method in the `/query` path:

curl -v -d "referenceName=1&start=14929&referenceBases=A&alternateBases=G&assemblyId=GRCh37&datasetIds=EGAD00000000028&includeDatsetResponses=ALL" https://localhost:5000/query
######
`curl -v -d "referenceName=1&start=14929&referenceBases=A&alternateBases=G&assemblyId=GRCh37&datasetIds=EGAD00000000028&includeDatsetResponses=ALL" https://localhost:5000/query`

```
> POST /query HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
Expand All @@ -376,13 +477,15 @@ Example of how to use the POST method in the "/query" path:
< Content-Type: application/json
< Content-Length: 1056
< Server: Werkzeug/0.14.1 Python/3.6.5
< Date: Mon, 11 Jun 2018 07:15:48 GMT
< Date: Wed, 30 Jan 2018 07:15:48 GMT
<
{
"beaconId": "ega-beacon",
"apiVersion": "0.4",
"apiVersion": "1.1.1",
"exists": true,
"error": null,
"error": {
"errorCode": 200
},
"alleleRequest": {
"referenceName": "1",
"start": 14929,
Expand Down Expand Up @@ -410,60 +513,60 @@ Example of how to use the POST method in the "/query" path:
"note": "This sample set comprises cases of schizophrenia with additional cognitive measurements, collected in Aberdeen, Scotland.",
"externalUrl": null,
"info": {},
"error": null
"error": {
"errorCode": 200
}
}
]
}
* Closing connection 0
```

`curl -v 'https://localhost:5000/query?&start=0&end=0&startMin=28000000&startMax=29000000&endMin=28000000&endMax=29000000&referenceBases=A&alternateBases=T&assemblyId=GRCh37&datasetIds=EGAD00000000028&includeDatasetResponses=ALL'`
Example of error:

`curl -v 'https://localhost:5000/query?&start=0&end=0&startMin=28000000&startMax=29000000&endMin=28000000&endMax=29000000&referenceBases=A&alternateBases=T&assemblyId=GRCh37&datasetIds=EGAD00000000028&includeDatasetResponses=ALL'`

```
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 5000 (#0)
> GET /query?&start=0&end=0&startMin=28000000&startMax=29000000&endMin=28000000&endMax=29000000&referenceBases=A&alternateBases=T&assemblyId=GRCh37&datasetIds=EGAD00000000028&includeDatasetResponses=ALL HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 400 BAD REQUEST
< Content-Type: application/json
< Content-Length: 791
< Server: Werkzeug/0.14.1 Python/3.6.5
< Date: Fri, 06 Jul 2018 09:15:39 GMT
<
{
"message": {
> POST /query HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 133
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 133 out of 133 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 1056
< Server: Werkzeug/0.14.1 Python/3.6.5
< Date: Wed, 30 Jan 2018 07:15:48 GMT
<
{
"beaconId": "ega-beacon",
"apiVersion": "0.4",
"exists": null,
"apiVersion": "1.1.1",
"exists": true,
"error": {
"errorCode": 400,
"errorMessage": "Missing mandatory parameter referenceName"
"errorMessage" : "User provided assemblyId (GRCh38) does not match with dataset assembly (GRCh37)"
},
"allelRequest": {
"referenceName": "0",
"start": 0,
"startMin": 28000000,
"startMax": 29000000,
"alleleRequest": {
"referenceName": "1",
"start": 14929,
"startMin": 0,
"startMax": 0,
"end": 0,
"endMin": 28000000,
"endMax": 29000000,
"endMin": 0,
"endMax": 0,
"referenceBases": "A",
"alternateBases": "T",
"variantType": "0",
"alternateBases": "G",
"assemblyId": "GRCh37",
"datasetIds": [
"EGAD00000000028"
],
"includeDatasetResponses": "ALL"
"includeDatasetResponses": "NONE"
},
"datasetAlleleResponses": []
"datasetAlleleResponses": null
}
}
* Closing connection 0

* Closing connection 0
```
11 changes: 7 additions & 4 deletions beacon.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -624,19 +624,22 @@ components:
example:
additionalInfoKey: additionalInfoValue
BeaconError:
description: >-
Beacon-specific error. This should be non-null in exceptional situations
only, in which case `exists` has to be null.
description: |
Status of the response. If there is no error, `errorCode` will always be `200`. If there is an error, check the documentation for the available values.

Although not recommended, it can be null for backward compatibility.
type: object
required:
- errorCode
properties:
errorCode:
type: integer
format: int32
example: 'same as HTTP status code'
default: 200
example: 400
errorMessage:
type: string
example: 'User provided assemblyId (GRCh38) does not match with dataset assembly (GRCh37)'
DataUseConditions:
type: object
required:
Expand Down