Along the lines of popular seismological web services (see e.g. the FDSN protocol), an eGSIM request requires:

1. An endpoint, i.e. an URL denoting a specific service
2. A method (GET vs POST) defining the type of request
3. Parameters for customizing the desired response data

### Requests endpoints

eGSIM implements three endpoints which perform three different types of analysis:

- {{ baseurl }}/{{ egsim_data.TRELLIS.path }} for Model-to-Model Comparison
- {{ baseurl }}/{{ egsim_data.RESIDUALS.path }} for Model-to-Data Comparison
- {{ baseurl }}/{{ egsim_data.TESTING.path }} for Model-to-Data Testing

### Requests methods

eGSIM services can be invoked using the two standard HTTP methods: GET or POST. Typically, POST request are defined to send data to create/update a resource on the server. In eGSIM, both methods perform the same task of querying data. We suggest to use the GET method for simple requests with few parameters and no uploaded file, and POST otherwise.

#### GET method

Requests issued with the GET method simply concatenate the parameters names and values directly in the URL:

{{ baseurl }}/<service>?name1=value1&name2=value2...

The portion of string after the question mark ? is called query string: as you can see, some characters are not safe, because they have special meanings and they will not be interpreted as they are (e.g. &) . As a rule of thumb, the only safe characters are the alphanumeric ones (letters lower or uppercase, and numbers), and the characters -_.~. All other characters should be escaped via percent encoding. E.g., in Python you can use the `urllib's quote` function:

    from urllib.parse import quote
    dip = 60.5
    vs30 = [700, 800]
    # convert to strings:
    dips = str(dip)  # "60.5"
    vs30s = ",".join(str(_) for _ in vs30)  # "700,800"
    # build query string:
    query_str = '?' + 'dip=' + quote(dips, '') + '&' + 'vs30=' + quote(vs30s, '')
    # the quote function has percent encoded the unsafe character "," into "%2C"
    # query_str has been therefore transformed from
    # "?dip=60.5&vs30=700,800"
    # to:
    # "?dip=60.5&vs30=700%2C800"

Percent encoding the parameters in a GET request can become quite cumbersome for complex parameter sets. In case, the user might be interested to issue POST requests instead.

Note: eGSIM considers safe the following characters according to this specification (but we cannot guarantee they will always be, therefore do not encode them at your risk): {{ query_params_safe_chars }}

#### POST method

Requests issued with the POST method should use the usual URL pattern: {{ baseurl }}/<service> and provide the parameters set by means of additional data as text in JSON or YAML format. This releases the user from encoding parameters and avoids writing long query strings as all parameters are provided in an external file. How to create a POST request depends on the software or programming language used. Here a code snippet for Python (see HOWTO Fetch Internet Resources Using The urllib Package for details):

    import json
    import yaml  # needs PyYAML installed
    # imports for Python3  (comment/remove in Python2):
    from urllib.request import Request, urlopen
    from urllib.error import URLError, HTTPError
    # imports for Python2 (comment/remove in Python3):
    from urllib2 import Request, urlopen, URLError, HTTPError

    # 1) Request using the GET method:
    req = Request("eGSIM endpoint URL with encoded special characters, if any")

    # 2a) Request using the POST method, assuming JSON text file:
    with open('/path/to/my/file.json', 'r') as stream:
        jsondata = json.load(f)
    req = Request("write here your eGSIM endpoint URL", data=jsondata)

    # 2b) Request using the POST method, assuming YAML or JSON text file
    #     (YAML is a superset of JSON and thus this works also with JSON files):
    with open('/path/to/my/file.yaml', 'r') as stream:
        yamldata = yaml.safe_load(stream))
    req = Request("write here your eGSIM endpoint URL", data=yamldata)

### Request parameters

eGSIM supports the following parameter types in a request:

- numeric
- text (denoted as string)
- Numeric array (list of numbers) or String array (list of strings). Equally spaced numeric arrays can be typed in the MATLAB® format start:step:end (e.g. 0:0.1:0.3 results in the sequence of values 0, 0.1, 0.2, 0.3)
- boolean (true or false)

To illustrate this with an example, assuming a service with endpoint http://egsim.org/example, requiring the following parameters:

- gsim (string array)
- dip (numeric)
- Vs30 (numeric array)
- mag (numeric array)

Then a user request might look like this:

GET | http://egsim.org/example?gsim=Bradley2013,Allen2012&dip=45&vs30=560,760&mag=3:0.5:5
GET (safe) | http://egsim.org/example?gsim=Bradley2013%2CAllen2012&dip=45&vs30=560%2C760&mag=3%3A0.5%3A5 (Note percent encoded characters)
POST See note | http://egsim.org/example
data (YAML file) | data (JSON file)
    gsim:
     - "Bradley2013"
     - "Allen2012"
    dip: 45
    vs30:
     - 560
     - 760
    mag: "3:0.5:5"
    {
      "gsim": ["Bradley2013", "Allen2012"],
      "dip": 45,
      "vs30": [560, 760],
      "mag": "3:0.5:5"
    }
Web GUI components (example) |
Gsim |
Dip |
Vs30 |
Mag |

Notes:

- In YAML and JSON format:
  - Strings should be wrapped in quotes (see e.g. "Bradley2013" in gsim)
  - Numeric ranges are not fully supported and should be input as strings (see mag in the examples)
  - Numeric arrays can be typed also as strings with spaces or commas as delimiters: this is for convenience the format used by the Web GUI, but if you create your own file we discourage it because unclear. In any case, in the examples, vs30 could have been input also as "560 760", "560,760" or "[560,760]"

The full description of the parameters and their constraints will be given in each service specific section below.

### Response data

#### Formats

All eGSIM services can return data at the least in CSV and JSON formatted text (bytes sequences). JSON is by far preferable in web applications (the eGSIM web GUI for instances requests and processes data in this format), and CSV files have the advantage to be easily visualizable in widely used spreadsheet software. If you want to fetch data in your client code, both formats are widely supported in most languages (see e.g., the MATLAB® jsonencode and csvread functions, or Python json and csv standard libraries)

All eGSIM services accept the following parameters in the request which will dictate the response format:

{% include "./request_template.html" with form=egsim_data.FORMAT.form %}

(the parameters above will be omitted for simplicity in the remainder of the document)

#### Errors

Unsuccessful requests might fail for several reasons. In case of client or server errors, such as e.g. bad or missing parameters, eGSIM always returns responses in JSON formatted byte strings following the google API specification. Example:

    {
    	"error": {
    		"code": 400,
    		"message": "input validation error",
    		"errors": [
    			{
    		    	"domain": "magnitude",
    		    	"message": "This field is required.",
    		    	"reason": "required"
    		  	},
    		  ...
    		]
    	}
    }

Notes:

- code is the standard HTTP numeric status code ≥400 and ≤ 500, and message is the associated text. These two properties will be always present in an error response. errors is present only if the error is due to invalid parameters in the request (in all other cases it's missing). If present, code is 400, and errors is a list of objects with these properties: domain (indicating the parameter name raising the error), message (indicating the error message) and reason (indicating the error reason)

For instance, this code snippet modified from the standard Python how-to reference shows how to issue a request to a eGSIM service and catch potential errors in both Python2 and 3 (tested with Python 2.7 and 3.6):

    import json

    # imports for Python3  (comment/remove in Python2):
    from urllib.request import Request, urlopen
    from urllib.error import URLError, HTTPError

    # imports for Python2 (comment/remove in Python3):
    from urllib2 import Request, urlopen, URLError, HTTPError

    req = Request("write here your eGSIM endpoint URL")
    try:
        data = json.loads(urlopen(req))
    except HTTPError as e2:
        # handle HTTP errors because of a server or client error, e.g.:
        print("Http error %d" % e2.code)
        # If you want to dig into details,
        # load the JSON formatted response into a Python dict:
        errordict = json.loads(e2.read())['error']
        # now you can access fields such as
        # errordict['message'], errordict.get('errors', [])
    except URLError as e1:
        # handle general url errors like network errors. e.g.:
        print("Url error. Reason: %s" % e1.reason)