From e20dac7335a3850feecc3e480a084484fe558b38 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Tue, 30 Jan 2024 12:18:07 +0100 Subject: [PATCH 01/12] Add initial framework for testing general api compliance --- pyproject.toml | 1 + .../tests/general/compliance_util.py | 558 ++ .../tests/general/openapi.json | 6651 +++++++++++++++++ .../tests/general/test_compliance.py | 1497 ++++ 4 files changed, 8707 insertions(+) create mode 100644 src/openeo_test_suite/tests/general/compliance_util.py create mode 100644 src/openeo_test_suite/tests/general/openapi.json create mode 100644 src/openeo_test_suite/tests/general/test_compliance.py diff --git a/pyproject.toml b/pyproject.toml index 2407c2f..e4def94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ dependencies = [ "pytest-html>=4.1.0", "stac-validator>=3.3.0", "pytest-metadata>=3.0.0", + "openapi-core>=0.18.2", ] classifiers = [ "Programming Language :: Python :: 3", diff --git a/src/openeo_test_suite/tests/general/compliance_util.py b/src/openeo_test_suite/tests/general/compliance_util.py new file mode 100644 index 0000000..3bbfa08 --- /dev/null +++ b/src/openeo_test_suite/tests/general/compliance_util.py @@ -0,0 +1,558 @@ +from openapi_core import Spec +import yaml +import json +import os +import uuid +import requests +import time + +from openeo_test_suite.lib.backend_under_test import get_backend_url + + +from openapi_core import validate_response +from openapi_core.contrib.requests import RequestsOpenAPIRequest +from openapi_core.contrib.requests import RequestsOpenAPIResponse +from openapi_core import V30ResponseValidator + + +def test_endpoint( + base_url: str, + endpoint_path: str, + test_name: str, + spec: Spec, + payload: dict = None, + bearer_token: str = None, + method: str = "GET", + expected_status_code: int = 200, + return_response: bool = False, +): + full_endpoint_url = f"{base_url}{endpoint_path}" + + if bearer_token is not None: + if method == "POST": + requests_response = requests.post( + full_endpoint_url, + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"{bearer_token}", + }, + ) + + requests_request = requests.Request( + "post", + full_endpoint_url, + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"{bearer_token}", + }, + ) + + elif method == "PUT": + requests_response = requests.put( + full_endpoint_url, + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"{bearer_token}", + }, + ) + + requests_request = requests.Request( + "put", + full_endpoint_url, + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"{bearer_token}", + }, + ) + + elif method == "PATCH": + requests_response = requests.patch( + full_endpoint_url, + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"{bearer_token}", + }, + ) + + requests_request = requests.Request( + "patch", + full_endpoint_url, + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"{bearer_token}", + }, + ) + + if method == "GET": + requests_response = requests.get( + full_endpoint_url, headers={"Authorization": f"{bearer_token}"} + ) + requests_request = requests.Request( + "get", full_endpoint_url, headers={"Authorization": f"{bearer_token}"} + ) + + elif method == "DELETE": + requests_response = requests.delete( + full_endpoint_url, headers={"Authorization": f"{bearer_token}"} + ) + requests_request = requests.Request( + "delete", + full_endpoint_url, + headers={"Authorization": f"{bearer_token}"}, + ) + # if both payload and bearer token are None, it can only be a simple get + else: + requests_response = requests.get(full_endpoint_url) + requests_request = requests.Request("get", full_endpoint_url) + + openapi_request = RequestsOpenAPIRequest(requests_request) + openapi_response = RequestsOpenAPIResponse(requests_response) + + try: + if openapi_response.status_code == expected_status_code: + validate_response( + openapi_request, openapi_response, spec=spec, cls=V30ResponseValidator + ) + else: + raise UnexpectedStatusCodeException( + endpoint=full_endpoint_url, + expected_status_code=expected_status_code, + actual_status_code=openapi_response.status_code, + auth=(bearer_token is not None), + ) + except Exception as e: + print_test_results(e, endpoint_path=endpoint_path, test_name=test_name) + if return_response: + return check_test_results(e), requests_response + else: + return check_test_results(e) + else: + if return_response: + return "", requests_response + else: + return "" + + +class UnexpectedStatusCodeException(Exception): + def __init__(self, endpoint, expected_status_code, actual_status_code, auth): + self.endpoint = endpoint + self.expected_status_code = expected_status_code + self.actual_status_code = actual_status_code + self.auth = auth + self.message = f'Unexpected status code for endpoint "{endpoint}": Expected {expected_status_code}, but received {actual_status_code}.' + super().__init__(self.message) + + +def get_batch_job_status(base_url: str, bearer_token: str, job_id: str): + return json.loads( + requests.get( + f"{base_url}/jobs/{job_id}", headers={"Authorization": f"{bearer_token}"} + ).content + )["status"] + + +def wait_job_statuses( + base_url: str, + bearer_token: str, + job_ids: list[str], + job_statuses: list[str], + timeout: int = 10, +): + """ + waits for jobs status to reach one of job_statuses, or times out after {timeout} seconds + + returns True if all jobs have reached desired status + returns False if timeout has been reached + """ + end_time = time.time() + timeout + while time.time() < end_time: + all_jobs_finished = True + for job_id in job_ids: + if all_jobs_finished: + all_jobs_finished = ( + get_batch_job_status( + base_url=base_url, bearer_token=bearer_token, job_id=job_id + ) + in job_statuses + ) + else: + break + if all_jobs_finished: + print("All jobs have reached their desired status.") + return True + time.sleep(1) + print("Waiting on jobs to reach desired status..") + print("Jobs failed to reach desired state, timeout has been reached.") + return False + + +def print_test_results(e: Exception, endpoint_path: str, test_name: str = "?"): + """ + prints the results of a openapi-core validation test + + e: the exception that was raised as a part of the response validation test + test_name: the name of the test that ought to be displayed + """ + print("") + print("------------------------------------------") + print( + f'Validation Errors from path: "{endpoint_path}" Path description: {test_name}' + ) + + # message is important + if type(e) is UnexpectedStatusCodeException: + print("") + print(e.message) + if e.auth and (e.actual_status_code == 500): + print( + "Bearer-Token invalid/no longer valid or if endpoint expects an id the item does not exist." + ) + elif e.actual_status_code == 500: + print("Endpoint expects an id and the item does not exist.") + elif e.actual_status_code == 404 or e.actual_status_code == 501: + print("Endpoint is not implemented, only an error if it is REQUIRED.") + elif e.actual_status_code == 410: + print( + "Endpoint is not providing requested resource as it is gone. Logs are not provided if job is queued or created." + ) + else: + print(f"Some other unexpected error code. {e.actual_status_code}") + # json_path and message are important + elif hasattr(e.__cause__, "schema_errors"): + errors = e.__cause__.schema_errors + for error in errors: + print("") + print(error.message) + print(error.json_path) + else: + print(e) + print("------------------------------------------") + print("") + + +def check_test_results(e: Exception): + """ + prints the results of a openapi-core validation test + + e: the exception that was raised as a part of the response validation test + test_name: the name of the test that ought to be displayed + """ + + # message is important + + fail_log = "" + if type(e) is UnexpectedStatusCodeException: + if e.auth and (e.actual_status_code == 500): + fail_log = "Bearer-Token invalid/no longer valid or if endpoint expects an id the item does not exist." + elif e.actual_status_code == 500: + fail_log = "Endpoint expects an id and the item does not exist." + elif e.actual_status_code == 404 or e.actual_status_code == 501: + fail_log = "Endpoint is not implemented, only an error if it is REQUIRED." + elif e.actual_status_code == 410: + fail_log = "Endpoint is not providing requested resource as it is gone. Logs are not provided if job is queued or created." + else: + fail_log = f"Some other unexpected error code. {e.actual_status_code}" + # json_path and message are important + elif hasattr(e.__cause__, "schema_errors"): + errors = e.__cause__.schema_errors + for error in errors: + fail_log += f"Message: {error.message} Json_path: {error.json_path} \n" + else: + fail_log = str(e) + + return fail_log + + +# THIS IS A WORKAROUND, +# this can be removed IF the cause of ServerNotFound Exception has been fixed +def adjust_server_in_yaml(path_to_yaml: str, endpoint: str): + with open(path_to_yaml, "r") as file: + data = yaml.safe_load(file) + + if "servers" in data and isinstance(data["servers"], list): + for server in data["servers"]: + if "url" in server and isinstance(server["url"], str): + server["url"] = endpoint + + with open(path_to_yaml, "w") as file: + yaml.dump(data, file) + + +def adjust_server_in_json(path_to_json, endpoint): + with open(path_to_json, "r") as file: + data = json.load(file) + + if "servers" in data and isinstance(data["servers"], list): + for server in data["servers"]: + if "url" in server and isinstance(server["url"], str): + server["url"] = endpoint + + with open(path_to_json, "w") as file: + json.dump(data, file, indent=4) + + +# JSON variant +def adjust_spec_json(path_to_json: str, endpoint: str): + adjust_server_in_json(path_to_json=path_to_json, endpoint=endpoint) + + with open(path_to_json, "r") as file: + data = json.load(file) + return Spec.from_dict(data, validator=None) + + +def adjust_spec_well_known_json(path_to_json: str, endpoint: str): + adjust_server_in_well_known_json(path_to_json=path_to_json, endpoint=endpoint) + + with open(path_to_json, "r") as file: + data = json.load(file) + return Spec.from_dict(data, validator=None) + + +def adjust_server_in_well_known_json(path_to_json, endpoint): + with open(path_to_json, "r") as file: + data = json.load(file) + + data["paths"]["/.well-known/openeo"]["get"]["servers"][0]["url"] = endpoint + + with open(path_to_json, "w") as file: + json.dump(data, file, indent=4) + + +# YAML variant +def adjust_spec_yaml(path_to_yaml: str, endpoint: str): + adjust_server_in_yaml(path_to_yaml=path_to_yaml, endpoint=endpoint) + + with open(path_to_yaml, "r") as file: + data = yaml.safe_load(file) + return Spec.from_dict(data, validator=None) + + +def validate_uri(value): + return True + + +extra_format_validators = { + "uri": validate_uri, +} + + +def unmarshal_commonmark(value): + return value + + +extra_format_unmarshallers = { + "commonmark": unmarshal_commonmark, +} + + +def get_examples_path(): + return os.path.join(os.getcwd(), "openeo_conformance_test/payload_examples") + + +def get_spec_path_json(): + return os.path.join(os.getcwd(), "src/openeo_test_suite/tests/general/openapi.json") + + +def get_process_list_path(): + return os.path.join(os.getcwd(), "tests/general/process_list.json") + + +def load_payloads_from_directory(directory_path: str) -> list[dict]: + for filename in os.listdir(directory_path): + if filename.endswith(".json"): + file_path = os.path.join(directory_path, filename) + with open(file_path, "r") as file: + try: + # Load the JSON data from the file + data = json.load(file) + yield json.dumps(data) + except json.JSONDecodeError: + print(f"Error decoding JSON in file: {filename}") + except Exception as e: + print(f"Error reading file: {filename} - {str(e)}") + + +def set_uuid_in_job(json_data): + if isinstance(json_data, str): + json_data = json.loads(json_data) + # Generate a new UUID + new_id = str(uuid.uuid4().hex) + # Set the 'id' field to the generated UUID + json_data["process"]["id"] = new_id + # Return the modified JSON object + return new_id, json.dumps(json_data) + + +def delete_id_resource( + base_url: str, endpoint_path: str, bearer_token: str, ids: list[str] +): + try: + for id in ids: + requests.delete( + f"{base_url}/{endpoint_path}/{id}", + headers={"Authorization": f"{bearer_token}"}, + ) + except Exception as e: + print(e) + + +def put_process_graphs(base_url: str, bearer_token: str): # TODO id and so forth + directory_path = get_examples_path() + examples_directory = "put_process_graphs" + + created_udp_ids = [] + payloads = load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + + try: + for payload in payloads: + id = str(uuid.uuid4().hex) + created_udp_ids.append(id) + requests.put( + f"{base_url}/process_graphs/{id}", + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"{bearer_token}", + }, + ) + except Exception as e: + print(e) + return created_udp_ids + + +def set_uuid_in_udp(json_data): + if isinstance(json_data, str): + json_data = json.loads(json_data) + # Generate a new UUID + new_id = str(uuid.uuid4().hex) + # Set the 'id' field to the generated UUID + json_data["id"] = new_id + # Return the modified JSON object + return new_id, json.dumps(json_data) + + +def post_jobs(base_url: str, bearer_token: str): + endpoint_path = "jobs" + directory_path = get_examples_path() + examples_directory = "post_jobs" + + created_batch_job_ids = [] + + payloads = load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + full_endpoint_url = f"{base_url}{endpoint_path}" + + # TESTING + for payload in payloads: + _, payload = set_uuid_in_job(payload) + + response = requests.post( + full_endpoint_url, + data=payload, + headers={ + "Content-Type": "application/json", + "Authorization": f"{bearer_token}", + }, + ) + created_batch_job_ids.append(response.headers["OpenEO-Identifier"]) + + return created_batch_job_ids + + +def post_start_jobs(base_url: str, bearer_token: str): + created_batch_job_ids = post_jobs(base_url=base_url, bearer_token=bearer_token) + + endpoint_path = "jobs" + endpoint_path_extra = "results" + + for job_id in created_batch_job_ids: + full_endpoint_url = f"{base_url}/{endpoint_path}/{job_id}/{endpoint_path_extra}" + requests.post(full_endpoint_url, headers={"Authorization": f"{bearer_token}"}) + + return created_batch_job_ids + + +def cancel_delete_jobs(base_url: str, bearer_token: str, job_ids: list[str]): + """ + Deletes and cancels all jobs with the given ids + """ + + endpoint_path = "jobs" + + for job_id in job_ids: + full_endpoint_url = f"{base_url}/{endpoint_path}/{job_id}" + + requests.delete(full_endpoint_url, headers={"Authorization": f"{bearer_token}"}) + + +def process_list_generator(filename: str): + with open(filename, "r") as file: + data = json.load(file) + for item in data: + yield item + + +def get_process_list(base_url: str): + endpoint_path = "processes" + + full_endpoint_url = f"{base_url}/{endpoint_path}" + + return json.loads(requests.get(full_endpoint_url).content)["processes"] + + +def get_access_token(): + # load_dotenv("..") + refresh_token = os.getenv("OIDC_EGI_REFRESH_TOKEN") + url = "https://aai.egi.eu/auth/realms/egi/protocol/openid-connect/token" + payload = f"grant_type=refresh_token&refresh_token={refresh_token}&client_id=token-portal&scope=openid%20email%20profile%20voperson_id%20eduperson_entitlement" + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.post(url, data=payload, headers=headers) + + if response.status_code == 200: + return json.loads(response.content)["access_token"] + return None + + +from urllib.parse import urlparse, urlunparse + + +def get_domain(request): + url = get_backend_url(request.config) + parsed_url = urlparse(url) + # Reconstruct the URL with scheme and netloc only. + return urlunparse((parsed_url.scheme, parsed_url.netloc, "", "", "", "")) + + +def get_version(request): + url = get_backend_url(request.config) + parsed_url = urlparse(url) + # Split the path and filter for the segment starting with 'openeo/' and having a version number format. + for segment in parsed_url.path.split("/"): + if segment.startswith("openeo") and len(segment.split("/")) > 1: + return segment + "/" + return "" + + +def get_base_url(request): + url = get_backend_url(request.config) + if not url: + url = "https://openeo-dev.eodc.eu/" + parsed_url = urlparse(url) + # If the scheme is missing, add 'https://'. + if not parsed_url.scheme: + url = "https://" + url + # If the path is missing or doesn't contain 'openeo', query the '.well-known' endpoint. + if not parsed_url.path or "openeo" not in parsed_url.path: + requests_response = requests.get(url + "/.well-known/openeo") + data = json.loads(requests_response.content) + url = data["versions"][0]["url"] + return url diff --git a/src/openeo_test_suite/tests/general/openapi.json b/src/openeo_test_suite/tests/general/openapi.json new file mode 100644 index 0000000..7d77155 --- /dev/null +++ b/src/openeo_test_suite/tests/general/openapi.json @@ -0,0 +1,6651 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "openEO API", + "version": "1.2.0", + "description": "The openEO API specification for interoperable cloud-based processing of large Earth observation datasets.\n\n**Conformance class:** `https://api.openeo.org/1.2.0`\n\n# API Principles\n\n## Language\n\nIn the specification the key words \u201cMUST\u201d, \u201cMUST NOT\u201d, \u201cREQUIRED\u201d, \u201cSHALL\u201d, \u201cSHALL NOT\u201d, \u201cSHOULD\u201d, \u201cSHOULD NOT\u201d, \u201cRECOMMENDED\u201d, \u201cMAY\u201d, and \u201cOPTIONAL\u201d in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.html) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174.html).\n\n## Casing\n\nUnless otherwise stated the API works **case sensitive**.\n\nAll names SHOULD be written in snake case, i.e. words are separated with one underscore character (`_`) and no spaces, with all letters lower-cased. Example: `hello_world`. This applies particularly to endpoints and JSON property names. HTTP header fields are generally case-insensitive according to [RFC 7230](https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2) and in the specification we follow their respective casing conventions, e.g. `Content-Type` or `OpenEO-Costs`, for better readability and consistency.\n\n## HTTP / REST\n\nThis uses [HTTP REST](https://en.wikipedia.org/wiki/Representational_state_transfer) [Level 2](https://martinfowler.com/articles/richardsonMaturityModel.html#level2) for communication between client and back-end server.\n\nPublic APIs MUST be available via HTTPS only. \n\nEndpoints are made use meaningful HTTP verbs (e.g. GET, POST, PUT, PATCH, DELETE) whenever technically possible. If there is a need to transfer big chunks of data for a GET requests to the back-end, POST requests MAY be used as a replacement as they support to send data via request body. Unless otherwise stated, PATCH requests are only defined to work on direct (first-level) children of the full JSON object. Therefore, changing a property on a deeper level of the full JSON object always requires to send the whole JSON object defined by the first-level property.\n\nNaming of endpoints follow the REST principles. Therefore, endpoints are centered around resources. Resource identifiers MUST be named with a noun in plural form except for single actions that can not be modelled with the regular HTTP verbs. Single actions MUST be single endpoints with a single HTTP verb (POST is RECOMMENDED) and no other endpoints beneath it.\n\nThe openEO API makes use of [HTTP Content Negotiation](https://www.rfc-editor.org/rfc/rfc9110.html#name-content-negotiation),\nincluding, but not limited to, the request headers `Accept`, `Accept-Charset` and `Accept-Language`.\n\n### JSON\n\nThe API uses JSON for request and response bodies whenever feasible. Services use JSON as the default encoding. Other encodings can be requested using HTTP Content Negotiation ([`Accept` header](https://www.rfc-editor.org/rfc/rfc9110.html#name-accept)). Clients and servers MUST NOT rely on the order in which properties appear in JSON. To keep the response size small, lists of resources (e.g. the list of batch jobs) usually should not include nested JSON objects, if this information can be requested from the individual resource endpoints (e.g. the metadata for a single batch job).\n\n### Charset\n\nServices use [UTF-8](https://en.wikipedia.org/wiki/UTF-8) as the default charset if not negotiated otherwise with HTTP Content Negotiation ([`Accept-Charset` header](https://www.rfc-editor.org/rfc/rfc9110.html#name-accept-charset)).\n\n## Web Linking\n\nThe API is designed in a way that to most entities (e.g. collections and processes) a set of links can be added. These can be alternate representations, e.g. data discovery via OGC WCS or OGC CSW, references to a license, references to actual raw data for downloading, detailed information about pre-processing and more. Clients should allow users to follow the links.\n\nWhenever links are utilized in the API, the description explains which relation (`rel` property) types are commonly used.\nA [list of standardized link relations types is provided by IANA](https://www.iana.org/assignments/link-relations/link-relations.xhtml) and the API tries to align whenever feasible.\n\nSome very common relation types - usually not mentioned explicitly in the description of `links` fields - are:\n\n1. `self`: which allows link to the location that the resource can be (permanently) found online.This is particularly useful when the data is data is made available offline, so that the downstream user knows where the data has come from.\n\n2. `alternate`: An alternative representation of the resource, may it be another metadata standard the data is available in or simply a human-readable version in HTML or PDF.\n\n3. `about`: A resource that is related or further explains the resource, e.g. a user guide.\n\n4. `canonical`: This relation type usually points to a publicly accessible and more long-lived URL for a resource that otherwise often requires (Bearer) authentication with a short-lived token.\nThis way the the exposed resources can be used by non-openEO clients without additional authentication steps.\nFor example, a shared user-defined process or batch job results could be exposed via a canonical link.\nIf a URL should be publicly available to everyone, it can simply a user-specific URL, e.g. `https://openeo.example/processes/john_doe/ndvi`.\nFor resources that should only be accessible to a certain group of user, a signed URL could be given, e.g. `https://openeo.example/processes/81zjh1tc2pt52gbx/ndvi`.\n\nGenerally, it is RECOMMENDED to add descriptive titles (propertty `title`) and media type information (propertty `type`) for a better user experience.\n\n## Error Handling\n\nThe success of requests MUST be indicated using [HTTP status codes](https://www.rfc-editor.org/rfc/rfc7231.html#section-6) according to [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html).\n\nIf the API responds with a status code between 100 and 399 the back-end indicates that the request has been handled successfully.\n\nIn general an error is communicated with a status code between 400 and 599. Client errors are defined as a client passing invalid data to the service and the service *correctly* rejecting that data. Examples include invalid credentials, incorrect parameters, unknown versions, or similar. These are generally \"4xx\" HTTP error codes and are the result of a client passing incorrect or invalid data. Client errors do *not* contribute to overall API availability. \n\nServer errors are defined as the server failing to correctly return in response to a valid client request. These are generally \"5xx\" HTTP error codes. Server errors *do* contribute to the overall API availability. Calls that fail due to rate limiting or quota failures MUST NOT count as server errors. \n\n### JSON error object\n\nA JSON error object SHOULD be sent with all responses that have a status code between 400 and 599.\n\n``` json\n{\n \"id\": \"936DA01F-9ABD-4D9D-80C7-02AF85C822A8\",\n \"code\": \"SampleError\",\n \"message\": \"A sample error message.\",\n \"url\": \"https://openeo.example/docs/errors/SampleError\"\n}\n```\n\nSending `code` and `message` is REQUIRED. \n\n* A back-end MAY add a free-form `id` (unique identifier) to the error response to be able to log and track errors with further non-disclosable details.\n* The `code` is either one of the [standardized textual openEO error codes](errors.json) or a proprietary error code.\n* The `message` explains the reason the server is rejecting the request. For \"4xx\" error codes the message explains how the client needs to modify the request.\n\n By default the message MUST be sent in English language. Content Negotiation is used to localize the error messages: If an `Accept-Language` header is sent by the client and a translation is available, the message should be translated accordingly and the `Content-Language` header must be present in the response. See \"[How to localize your API](http://apiux.com/2013/04/25/how-to-localize-your-api/)\" for more information.\n* `url` is an OPTIONAL attribute and contains a link to a resource that is explaining the error and potential solutions in-depth.\n\n### Standardized status codes\n\nThe openEO API usually uses the following HTTP status codes for successful requests: \n\n- **200 OK**:\n Indicates a successful request **with** a response body being sent.\n- **201 Created**\n Indicates a successful request that successfully created a new resource. Sends a `Location` header to the newly created resource **without** a response body.\n- **202 Accepted**\n Indicates a successful request that successfully queued the creation of a new resource, but it has not been created yet. The response is sent **without** a response body.\n- **204 No Content**:\n Indicates a successful request **without** a response body being sent.\n\nThe openEO API has some commonly used HTTP status codes for failed requests: \n\n- **400 Bad Request**:\n The back-end responds with this error code whenever the error has its origin on client side and no other HTTP status code in the 400 range is suitable.\n\n- **401 Unauthorized**:\n The client did not provide any authentication details for a resource requiring authentication or the provided authentication details are not correct.\n\n- **403 Forbidden**:\n The client did provided correct authentication details, but the privileges/permissions of the provided credentials do not allow to request the resource.\n\n- **404 Not Found**:\n The resource specified by the path does not exist, i.e. one of the resources belonging to the specified identifiers are not available at the back-end.\n *Note:* Unsupported endpoints MAY also return HTTP status code 501.\n\n- **500 Internal Server Error**:\n The error has its origin on server side and no other status code in the 500 range is suitable.\n\n- **501 Not Implemented**:\n The requested endpoint is specified by the openEO API, but is not implemented (yet) by the back-end.\n *Note:* Unsupported endpoints MAY also return HTTP status code 404.\n\n\nIf a HTTP status code in the 400 range is returned, the client SHOULD NOT repeat the request without modifications. For HTTP status code in the 500 range, the client MAY repeat the same request later.\n\nAll HTTP status codes defined in RFC 7231 in the 400 and 500 ranges can be used as openEO error code in addition to the most used status codes mentioned here. Responding with openEO error codes 400 and 500 SHOULD be avoided in favor of any more specific standardized or proprietary openEO error code.\n\n## Temporal data\n\nDate, time, intervals and durations are formatted based on ISO 8601 or its profile [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) whenever there is an appropriate encoding available in the standard. All temporal data are specified based on the Gregorian calendar.\n\n# Authentication\n\nThe openEO API offers two forms of authentication by default:\n* OpenID Connect (recommended) at `GET /credentials/oidc`\n* Basic at `GET /credentials/basic`\n \nAfter authentication with any of the methods listed above, the tokens obtained during the authentication workflows can be sent to protected endpoints in subsequent requests.\n\nFurther authentication methods MAY be added by back-ends.\n\n\n\n**Note:** Although it is possible to request several public endpoints for capabilities and discovery that don't require authorization, it is RECOMMENDED that clients (re-)request the public endpoints that support Bearer authentication with the Bearer token once available to also retrieve any private data that is made available specifically for the authenticated user.\nThis may require that clients clear any cached data they retrieved from public endpoints before.\n\n# Cross-Origin Resource Sharing (CORS)\n\n> Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources [...] on a web page to be requested from another domain outside the domain from which the first resource was served. [...]\n> CORS defines a way in which a browser and server can interact to determine whether or not it is safe to allow the cross-origin request. It allows for more freedom and functionality than purely same-origin requests, but is more secure than simply allowing all cross-origin requests.\n\nSource: [https://en.wikipedia.org/wiki/Cross-origin_resource_sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)\n\nopenEO-based back-ends are usually hosted on a different domain / host than the client that is requesting data from the back-end. Therefore most requests to the back-end are blocked by all modern browsers. This leads to the problem that the JavaScript library and any browser-based application can't access back-ends. Therefore, all back-end providers SHOULD support CORS to enable browser-based applications to access back-ends. [CORS is a recommendation of the W3C organization](https://www.w3.org/TR/cors/). The following chapters will explain how back-end providers can implement CORS support.\n\n**Tip**: Most servers can send the required headers and the responses to the OPTIONS requests automatically for all endpoints. Otherwise you may also use a proxy server to add the headers and OPTIONS responses.\n\n## CORS headers\n\nThe following headers MUST be included with every response:\n\n| Name | Description | Example |\n| -------------------------------- | ------------------------------------------------------------ | ------- |\n| Access-Control-Allow-Origin | Allowed origin for the request, including protocol, host and port or `*` for all origins. It is RECOMMENDED to return the value `*` to allow requests from browser-based implementations such as the Web Editor. | `*` |\n| Access-Control-Expose-Headers | Some endpoints require to send additional HTTP response headers such as `OpenEO-Identifier` and `Location`. To make these headers available to browser-based clients, they MUST be white-listed with this CORS header. The following HTTP headers are white-listed by browsers and MUST NOT be included: `Cache-Control`, `Content-Language`, `Content-Length`, `Content-Type`, `Expires`, `Last-Modified` and `Pragma`. At least the following headers MUST be listed in this version of the openEO API: `Link`, `Location`, `OpenEO-Costs` and `OpenEO-Identifier`. | `Link, Location, OpenEO-Costs, OpenEO-Identifier` |\n\n\n\n### Example request and response\n\nRequest:\n\n```http\nPOST /api/v1/jobs HTTP/1.1\nHost: openeo.example\nOrigin: https://company.example:8080\nAuthorization: Bearer basic//ZXhhbXBsZTpleGFtcGxl\n```\n\nResponse:\n\n```http\nHTTP/1.1 201 Created\nAccess-Control-Allow-Origin: *\nAccess-Control-Expose-Headers: Location, OpenEO-Identifier, OpenEO-Costs, Link\nContent-Type: application/json\nLocation: https://openeo.example/api/v1/jobs/abc123\nOpenEO-Identifier: abc123\n```\n\n## OPTIONS method\n\nAll endpoints must respond to the `OPTIONS` HTTP method. This is a response for the preflight requests made by web browsers before sending the actual request (e.g. `POST /jobs`). It needs to respond with a status code of `204` and no response body.\n**In addition** to the HTTP headers shown in the table above, the following HTTP headers MUST be included with every response to an `OPTIONS` request:\n\n| Name | Description | Example |\n| -------------------------------- | ------------------------------------------------------------ | ------- |\n| Access-Control-Allow-Headers | Comma-separated list of HTTP headers allowed to be sent with the actual (non-preflight) request. MUST contain at least `Authorization` if any kind of authorization is implemented by the back-end. | `Authorization, Content-Type` |\n| Access-Control-Allow-Methods | Comma-separated list of HTTP methods allowed to be requested. Back-ends MUST list all implemented HTTP methods for the endpoint. | `OPTIONS, GET, POST, PATCH, PUT, DELETE` |\n| Content-Type | SHOULD return the content type delivered by the request that the permission is requested for. | `application/json` |\n\n### Example request and response\n\nRequest:\n\n```http\nOPTIONS /api/v1/jobs HTTP/1.1\nHost: openeo.example\nOrigin: https://company.example:8080\nAccess-Control-Request-Method: POST \nAccess-Control-Request-Headers: Authorization, Content-Type\n```\n\nNote that the `Access-Control-Request-*` headers are automatically attached to the requests by the browsers.\n\nResponse:\n\n```http\nHTTP/1.1 204 No Content\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: OPTIONS, GET, POST, PATCH, PUT, DELETE\nAccess-Control-Allow-Headers: Authorization, Content-Type\nAccess-Control-Expose-Headers: Location, OpenEO-Identifier, OpenEO-Costs, Link\nContent-Type: application/json\n```\n\n# Processes\n\nA **process** is an operation that performs a specific task on a set of parameters and returns a result. An example is computing a statistical operation, such as mean or median, on selected EO data. A process is similar to a function or method in programming languages. In openEO, processes are used to build a chain of processes ([process graph](#section/Processes/Process-Graphs)), which can be applied to EO data to derive your own findings from the data.\n\nA **predefined process** is a process provided by the *back-end*. There is a set of predefined processes by openEO to improve interoperability between back-ends.\nBack-ends SHOULD follow these specifications whenever possible. Not all processes need to be implemented by all back-ends. See the **[process reference](https://processes.openeo.org)** for predefined processes.\n\nA **user-defined process** is a process defined by the *user*. It can directly be part of another process graph or be stored as custom process on a back-end. Internally, it is a *process graph* with a variety of additional metadata.\n\nA **process graph** chains specific process calls from the set of predefined and user-defined processes together. A process graph itself can be stored as a (user-defined) process again. Similarly to scripts in the context of programming, process graphs organize and automate the execution of one or more processes that could alternatively be executed individually. In a process graph, processes need to be specific, i.e. concrete values or \"placeholders\" for input parameters need to be specified. These values can be scalars, arrays, objects, references to parameters or previous computations or other process graphs.\n\n## Defining Processes\n\nBack-ends and users MAY define new proprietary processes for their domain. \n\n**Back-end providers** MUST follow the schema for predefined processes as in [`GET /processes`](#operation/list-processes) to define new processes. This includes:\n\n* Choosing a intuitive process id, consisting of only letters (a-z), numbers and underscores. It MUST be unique across the predefined processes.\n* Defining the parameters and their exact (JSON) schemes.\n* Specifying the return value of a process also with a (JSON) schema.\n* Providing examples or compliance tests.\n* Trying to make the process universally usable so that other back-end providers or openEO can adopt it.\n\n**Users** MUST follow the schema for user-defined processes as in [`GET /process_graphs/{process_graph_id}`](#operation/describe-custom-process) to define new processes. This includes:\n\n* Choosing a intuitive name as process id, consisting of only letters (a-z), numbers and underscores. It MUST be unique per user across the user-defined processes.\n* Defining the algorithm as a process graph.\n* Optionally, specifying the additional metadata for processes.\n\nIf new process are potentially useful for other back-ends the openEO consortium is happily accepting [pull requests](https://github.com/Open-EO/openeo-processes/pulls) to include them in the list of predefined processes.\n\n### Schemas\n\nEach process parameter and the return values of a process define a schema that the value MUST comply to. The schemas are based on [JSON Schema draft-07](http://json-schema.org/).\n\nMultiple custom keywords have been defined:\n* `subtype` for more fine-grained data-types than JSON Schema supports.\n* `dimensions` to further define the dimension types required if the `subtype` is `datacube`.\n* `parameters` to specify the parameters of a process graph if the `subtype` is `process-graph`.\n* `returns` to describe the return value of a process graph if the `subtype` is `process-graph`.\n\n### Subtypes\n\nJSON Schema allows to specify only a small set of native data types (string, boolean, number, integer, array, object, null).\nTo support more fine grained data types, a custom [JSON Schema keyword](https://json-schema.org/draft-07/json-schema-core.html#rfc.section.6.4) has been defined: `subtype`.\nIt works similarly as the JSON Schema keyword [`format`](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.7)\nand standardizes a number of openEO related data types that extend the native data types, for example:\n`bounding-box` (object with at least `west`, `south`, `east` and `north` properties),\n`date-time` (string representation of date and time following RFC 3339),\n`datacube` (a datacube with dimensions), etc.\nThe subtypes should be re-used in process schema definitions whenever suitable.\n\nIf a general data type such as `string` or `number` is used in a schema, all subtypes with the same parent data type can be passed, too.\nClients should offer make passing subtypes as easy as passing a general data type.\nFor example, a parameter accepting strings must also allow passing a string with subtype `date` and thus clients should encourage this by also providing a date-picker.\n\nA list of predefined subtypes is available as JSON Schema in [openeo-processes](https://github.com/Open-EO/openeo-processes).\n\n## Process Graphs\n\nAs defined above, a **process graph** is a chain of processes with explicit values for their parameters.\nTechnically, a process graph is defined to be a graph of connected processes with exactly one node returning the final result:\n\n```\n := {\n \"\": ,\n ...\n}\n```\n\n`` is a unique key within the process graph that is used to reference (the return value of) this process in arguments of other processes. The identifier is unique only strictly within itself, excluding any parent and child process graphs. Process node identifiers are also strictly scoped and can not be referenced from child or parent process graphs. Circular references are not allowed.\n\nNote: We provide a non-binding [JSON Schema for basic process graph validation](assets/pg-schema.json).\n\n### Processes (Process Nodes)\n\nA single node in a process graph (i.e. a specific instance of a process) is defined as follows:\n\n```\n := {\n \"process_id\": ,\n \"namespace\": / null,\n \"description\": ,\n \"arguments\": ,\n \"result\": true / false\n}\n```\nA process node MUST always contain key-value-pairs named `process_id` and `arguments`. It MAY contain a `description`.\n\nOne of the nodes in a map of processes (the final one) MUST have the `result` flag set to `true`, all the other nodes can omit it as the default value is `false`. Having such a node is important as multiple end nodes are possible, but in most use cases it is important to exactly specify the return value to be used by other processes. Each child process graph must also specify a result node similar to the \"main\" process graph.\n\n`process_id` MUST be a valid process ID in the `namespace` given. Clients SHOULD warn the user if a user-defined process is added with the same identifier as one of the predefined process.\n\n### Arguments\n\nA process can have an arbitrary number of arguments. Their name and value are specified \nin the process specification as an object of key-value pairs:\n\n```\n := {\n \"\": \n}\n```\n\n**Notes:**\n- The specified data types are the native data types supported by JSON, except for `ResultReference`, `UserDefinedProcess` and `ParameterReference`.\n- Objects are not allowed to have keys with the following reserved names:\n\n * `from_node`, except for objects of type `ResultReference`\n * `process_graph`, except for objects of type `UserDefinedProcess`\n * `from_parameter`, except for objects of type `ParameterReference`\n\n- Arrays and objects can also contain a `ResultReference`, a `UserDefinedProcess` or a `ParameterReference`. So back-ends must *fully* traverse the process graphs, including all children.\n\n### Accessing results of other process nodes\n\nA value of type `` is an object with a key `from_node` and a `` as corresponding value:\n\n```\n := {\n \"from_node\": \"\"\n}\n```\n\nThis tells the back-end that the process expects the result (i.e. the return value) from another process node to be passed as argument.\nThe `` is strictly scoped and can only reference nodes from within the same process graph, not child or parent process graphs.\n\n### Child processes\n\nSome processes can run child processes, which is similar to the concept that other programming languages call\n[callbacks](https://en.wikipedia.org/wiki/Callback_(computer_programming)) or lambda functions.\nEach child process is simply a user-defined process again and can in theory be arbritarily complex.\n\nA very simple example would be to calculate the absolute value of each pixel in a data cube.\nThis can be achieved in openEO by using the `apply` process which gets the `absolute` process passed as child process.\nIn this example, the \"child\" processes consists of a single process `absolute`, but it can also be a more complex computation such as an NDVI or a prediciton based on a machine learning model.\n\n**Example**: \n\nA `` argument MUST at least consist of an object with a key `process_graph`.\nOptionally, it can also be described with the same additional properties available for predefined processes such as an id, parameters, return values etc.\nWhen embedded in a process graph, these additional properties of a user-defined process are usually not used, except for validation purposes.\n\n```\n := {\n \"process_graph\": ,\n ...\n}\n```\n\n### Accessing process parameters\n\nA \"parent\" process that works with a child process can make so called *process graph parameters*\navailable to the \"child\" logic.\nProcesses in the \"child\" process graph can access these parameters by passing a `ParameterReference` object as argument.\nIt is an object with key `from_parameter` specifying the name of the process graph parameter:\n\n```\n := {\n \"from_parameter\": \"\"\n}\n```\n\nThe parameter names made available for `` are defined and passed to the process graph by one of the parent entities.\nThe parent could be a process (such as `apply` or `reduce_dimension`) or something else that executes a process graph (a secondary web service for example).\nIf the parent is a process, the parameter are defined in the [`parameters` property](#section/Processes/Defining-Processes) of the corresponding JSON Schema.\n\nIn case of the example given above, the parameter `process` in the process [`apply`](https://processes.openeo.org/#apply) defines two process graph parameters: `x` (the value of each pixel that will be processed) and `context` (additional data passed through from the user).\nThe process `absolute` expects an argument with the same name `x`.\nThe process graph for the example would look as follows:\n\n```\n{\n \"process_id\": \"apply\",\n \"arguments\": {\n \"data\": {\"from_node\": \"loadcollection1\"}\n \"process\": {\n \"process_graph\": {\n \"abs1\": {\n \"process_id\": \"absolute\",\n \"arguments\": {\n \"x\": {\"from_parameter\": \"x\"}\n },\n \"result\": true\n }\n }\n }\n }\n}\n```\n\n`loadcollection1` would be a result from another process, which is not part of this example.\n\n**Important:** `` is less strictly scoped than ``.\n`` can be any parameter from the process graph or any of its parents.\n\nThe value for the parameter MUST be resolved as follows:\n1. In general the most specific parameter value is used. This means the parameter value is resolved starting from the current scope and then checking each parent for a suitable parameter value until a parameter values is found or the \"root\" process graph has been reached.\n2. In case a parameter value is not available, the most unspecific default value from the process graph parameter definitions are used. For example, if default values are available for the root process graph and all children, the default value from the root process graph is used.\n3. If no default values are available either, the error `ProcessParameterMissing` must be thrown.\n\n### Full example for an EVI computation\n\nDeriving minimum EVI (Enhanced Vegetation Index) measurements over pixel time series of Sentinel 2 imagery. The main process graph in blue, child process graphs in yellow:\n\n![Graph with processing instructions](assets/pg-evi-example.png)\n\nThe process graph for the algorithm: [pg-evi-example.json](assets/pg-evi-example.json)\n\n## Data Processing\n\nProcesses can run in three different ways:\n\n1. Results can be pre-computed by creating a ***batch job***. They are submitted to the back-end's processing system, but will remain inactive until explicitly put into the processing queue. They will run only once and store results after execution. Results can be downloaded. Batch jobs are typically time consuming and user interaction is not possible although log files are generated for them. This is the only mode that allows to get an estimate about time, volume and costs beforehand.\n\n2. A more dynamic way of processing and accessing data is to create a **secondary web service**. They allow web-based access using different protocols such as [OGC WMS](http://www.opengeospatial.org/standards/wms), [OGC WCS](http://www.opengeospatial.org/standards/wcs), [OGC API - Features](https://www.ogc.org/standards/ogcapi-features) or [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames). Some protocols such as the OGC WMS or XYZ tiles allow users to change the viewing extent or level of detail (zoom level). Therefore, computations often run *on demand* so that the requested data is calculated during the request. Back-ends should make sure to cache processed data to avoid additional/high costs and reduce waiting times for the user.\n\n3. Processes can also be executed **on-demand**\u00a0(i.e. synchronously). Results are delivered with the request itself and no job is created. Only lightweight computations, for example previews, should be executed using this approach as timeouts are to be expected for [long-polling HTTP requests](https://www.pubnub.com/blog/2014-12-01-http-long-polling/).\n\n### Validation\n\nProcess graph validation is a quite complex task. There's a [JSON schema](assets/pg-schema.json) for basic process graph validation. It checks the general structure of a process graph, but only checking against the schema is not fully validating a process graph. Note that this JSON Schema is probably good enough for a first version, but should be revised and improved for production. There are further steps to do:\n\n1. Validate whether there's exactly one `result: true` per process graph.\n2. Check whether the process names that are referenced in the field `process_id` are actually available in the corresponding `namespace`.\n3. Validate all arguments for each process against the JSON schemas that are specified in the corresponding process specifications.\n4. Check whether the values specified for `from_node` have a corresponding node in the same process graph.\n5. Validate whether the return value and the arguments requesting a return value with `from_node` are compatible.\n7. Check the content of arrays and objects. These could include parameter and result references (`from_node`, `from_parameter` etc.).\n\n\n### Execution\n\nTo process the process graph on the back-end you need to go through all nodes/processes in the list and set for each node to which node it passes data and from which it expects data. In another iteration the back-end can find all start nodes for processing by checking for zero dependencies.\n\nYou can now start and execute the start nodes (in parallel, if possible). Results can be passed to the nodes that were identified beforehand. For each node that depends on multiple inputs you need to check whether all dependencies have already finished and only execute once the last dependency is ready.\n\nPlease be aware that the result node (`result` set to `true`) is not necessarily the last node that is executed. The author of the process graph may choose to set a non-end node to the result node!", + "contact": { + "name": "openEO Consortium", + "url": "https://openeo.org", + "email": "openeo.psc@uni-muenster.de" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "externalDocs": { + "description": "openEO Documentation", + "url": "https://openeo.org/documentation/1.0/" + }, + "tags": [ + { + "name": "Capabilities", + "description": "General information about the API implementation and other supported capabilities at the back-end." + }, + { + "name": "Account Management", + "description": "The following endpoints handle user profiles, accounting and authentication. See also [Authentication](#section/Authentication). In general, the openEO API only defines a minimum subset of user management and accounting functionality. It allows to\n\n* [authenticate and authorize](http://www.differencebetween.net/technology/difference-between-authentication-and-authorization/) a user, which may include [user registration with OpenID Connect](http://openid.net/specs/openid-connect-registration-1_0.html),\n* handle storage space limits (disk quota),\n* manage billing, which includes to\n * query the credit a user has available,\n * estimate costs for certain operations (data processing and downloading),\n * get information about produced costs,\n * limit costs of certain operations.\n\nTherefore, the API leaves some aspects open that have to be handled by the back-ends separately, including \n\n* credentials recovery, e.g. retrieving a forgotten password\n* user data management, e.g. changing the users payment details or email address\n* payments, i.e. topping up credits for pre-paid services or paying for post-paid services\n* other accounting related tasks, e.g. creating invoices,\n* user registration (except for [user registration with OpenID Connect](http://openid.net/specs/openid-connect-registration-1_0.html))." + }, + { + "name": "EO Data Discovery", + "description": "These endpoints allow to list the collections that are available at the back-end and can be used as data cubes for data processing.\n\n## STAC\n\nFor data discovery of Earth Observation Collections at the back-ends, openEO strives for compatibility with the specifications [SpatioTemporal Asset Catalog (STAC)](https://stacspec.org/) and [OGC API - Features - Part 1: Core](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html) as far as possible. Implementing the data discovery endpoints of openEO also produced valid STAC API 1.0 and OGC API - Features 1.0 responses, including ([partial](#provide-data-for-download)) compatibility with their APIs. \n\nThe data discovery endpoints `GET /collections` and `GET /collections/{collection_id}` are compatible with OGC API - Features and STAC. Both specifications define additional endpoints that need to be implemented to be fully compatible. The additional endpoints can easily be integrated into an openEO API implementation. A rough list of actions for compatibility is available below, but please refer to their specifications to find out the full details.\n\n**Important:** [STAC specification](https://github.com/radiantearth/stac-spec) and [STAC API](https://github.com/radiantearth/stac-api-spec) are different specifications and have different version numbers after version 0.9.0.\nThe openEO API implements STAC API versions >= 0.9.0 (preferrably [STAC API version 1.0.0](https://github.com/radiantearth/stac-api-spec/blob/v1.0.0/README.md), but [0.9.0](https://github.com/radiantearth/stac-spec/blob/v0.9.0/api-spec/README.md) is allowed for backward compatibility), which allows to serve all STAC specification versions in the range of 0.9.x and 1.x.x (see the `stac_version` property).\n\n### Content Extensions\n\nSTAC has several [extensions](https://stac-extensions.github.io) that can be used to better describe your data. Clients and server are not required to implement all of them, so be aware that some clients may not be able to read all your metadata.\n\nSome commonly used extensions that are relevant for datasets exposed through the openEO API are:\n\n- Data Cube extension (part of the openEO API)\n- [EO (Electro-Optical) extension](https://github.com/stac-extensions/eo)\n- [Processing extension](https://github.com/stac-extensions/processing)\n- [Raster extension](https://github.com/stac-extensions/raster)\n- [SAR extension](https://github.com/stac-extensions/sar)\n- [Satellite extension](https://github.com/stac-extensions/sat)\n- [Scientific Citation extension](https://github.com/stac-extensions/scientific)\n\n### Provide data for download\n\nIf you'd like to provide your data for download in addition to offering the cloud processing service, you can implement the full STAC API. Therefore you can implement the endpoints `GET /collections/{collection_id}/items` and `GET /collections/{collection_id}/items/{feature_id}` to support retrieval of individual items. To benefit from the STAC ecosystem and allow searching for items you can also implement `POST /search` and `GET /search`. Further information can be found in the [STAC API repository](https://github.com/radiantearth/stac-spec/tree/v0.9.0/api-spec).\n\n### API Extensions\n\nSTAC API has several [extensions](https://stac-api-extensions.github.io) that can be implemented on top of the openEO API to enrich the API functionality, e.g. for searching." + }, + { + "name": "Process Discovery", + "description": "These endpoints allow to list the predefined processes that are available at the back-end. To list user-defined processes see '[User-Defined Processes](#tag/User-Defined-Processes)'." + }, + { + "name": "User-Defined Processes", + "description": "These endpoints allow to store and manage user-defined processes with their process graphs at the back-end." + }, + { + "name": "Data Processing", + "description": "Organizes and manages data processing on the back-end, either as synchronous on-demand computation or batch jobs." + }, + { + "name": "Batch Jobs", + "description": "Management of batch processing tasks (jobs) and their results." + }, + { + "name": "Secondary Services", + "description": "On-demand access to data using other web service protocols." + }, + { + "name": "File Storage", + "description": "Management of user-uploaded assets and processed data." + } + ], + "servers": [ + { + "url": "https://openeo-dev.eodc.eu/openeo/1.1.0/", + "description": "The URL of the API MAY freely be chosen by the back-end providers. The path, including API versioning, is a *recommendation* only. Nevertheless, all servers MUST support HTTPS as the authentication methods are not secure with HTTP only!", + "variables": { + "version": { + "default": "v1", + "description": "API versioning is RECOMMENDED. As the openEO API is following\n[SemVer](https://semver.org/) only the **major** part of the version\nnumbers SHOULD be used for API versioning in the URL. To make clear\nthat it is a version number, it is RECOMMENDED to add the prefix `v`.\n\nExample: API version `1.2.3` is recommended to use `v1`.\n\nThe reason to only consider the major part is that backward-incompatible\nchanges are introduced by major changes only. All changes from minor\nand patch releases can usually be integrated without breakages and thus\na change in the URL is not really needed.\n\nThe version number in the URL MUST not be used by the clients to detect\nthe version number of the API. Use the version number returned in the\nproperty `api_version` from `GET /` instead." + } + } + } + ], + "paths": { + "/": { + "get": { + "summary": "Information about the back-end", + "operationId": "capabilities", + "description": "Lists general information about the back-end, including which version and endpoints of the openEO API are supported. May also include billing information.", + "tags": [ + "Capabilities" + ], + "security": [ + {} + ], + "responses": { + "200": { + "description": "Information about the API version and supported endpoints /\nfeatures.\n\nThis endpoint MUST always be available for the API to be valid.", + "content": { + "application/json": { + "schema": { + "title": "Capabilities", + "type": "object", + "required": [ + "id", + "title", + "description", + "api_version", + "backend_version", + "stac_version", + "endpoints", + "links" + ], + "properties": { + "api_version": { + "type": "string", + "description": "Version number of the openEO specification this back-end implements.", + "enum": [ + "1.2.0" + ] + }, + "backend_version": { + "type": "string", + "description": "Version number of the back-end implementation.\nEvery change on back-end side MUST cause a change of the version number.", + "example": "1.1.2" + }, + "stac_version": { + "$ref": "#/components/schemas/stac_version" + }, + "type": { + "type": "string", + "enum": [ + "Catalog" + ], + "description": "For STAC versions >= 1.0.0-rc.1 this field is required.", + "example": "Catalog" + }, + "id": { + "type": "string", + "description": "Identifier for the service.\nThis field originates from STAC and is used as unique identifier for the STAC catalog available at `/collections`.", + "example": "cool-eo-cloud" + }, + "title": { + "type": "string", + "description": "The name of the service.", + "example": "Example Cloud Corp." + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "A description of the service, which allows the service provider to introduce the user to its service.\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", + "example": "This service is provided to you by [Example Cloud Corp.](https://cloud.example). It implements the full openEO API and allows to process a range of 999 EO data sets, including \n\n* Sentinel 1/2/3 and 5\n* Landsat 7/8\n\nA free plan is available to test the service. For further information please contact our customer service at [support@cloud.example](mailto:support@cloud.example)." + }, + "conformsTo": { + "$ref": "#/components/schemas/conformsTo" + }, + "production": { + "$ref": "#/components/schemas/production" + }, + "endpoints": { + "type": "array", + "description": "Lists all supported endpoints. Supported are all endpoints, which are implemented, return usually a 2XX or 3XX HTTP status code and are fully compatible to the API specification. An entry for this endpoint (path `/` with method `GET`) SHOULD NOT be listed. Each path MUST only be listed once in the array.", + "items": { + "title": "Endpoint", + "type": "object", + "required": [ + "path", + "methods" + ], + "properties": { + "path": { + "description": "Path to the endpoint, relative to the URL of this endpoint. In general the paths MUST follow the paths specified in the openAPI specification as closely as possible. Therefore, paths MUST be prepended with a leading slash, but MUST NOT contain a trailing slash. Variables in the paths MUST be placed in curly braces and follow the parameter names in the openAPI specification, e.g. `{job_id}`.", + "type": "string" + }, + "methods": { + "description": "Supported HTTP verbs in uppercase. It is OPTIONAL to list `OPTIONS` as method (see the [CORS section](#section/Cross-Origin-Resource-Sharing-(CORS))).", + "type": "array", + "items": { + "type": "string", + "enum": [ + "GET", + "POST", + "PATCH", + "PUT", + "DELETE", + "OPTIONS" + ] + } + } + } + }, + "example": [ + { + "path": "/collections", + "methods": [ + "GET" + ] + }, + { + "path": "/collections/{collection_id}", + "methods": [ + "GET" + ] + }, + { + "path": "/processes", + "methods": [ + "GET" + ] + }, + { + "path": "/jobs", + "methods": [ + "GET", + "POST" + ] + }, + { + "path": "/jobs/{job_id}", + "methods": [ + "GET", + "DELETE", + "PATCH" + ] + } + ] + }, + "billing": { + "title": "Billing", + "description": "Billing related data, e.g. the currency used or available plans to process jobs.\nThis property MUST be specified if the back-end uses any billing related API functionalities, e.g. budgeting or estimates.\nThe absence of this property doesn't mean the back-end is necessarily free to use for all. Providers may choose to bill users outside of the API, e.g. with a monthly fee that is not depending on individual API interactions.", + "type": "object", + "required": [ + "currency" + ], + "properties": { + "currency": { + "description": "The currency the back-end is billing in. The currency MUST be either a valid currency code as defined in ISO-4217 or a back-end specific unit that is used for billing such as credits, tiles or CPU hours. If set to `null`, budget and costs are not supported by the back-end and users can't be charged.", + "type": "string", + "nullable": true, + "example": "USD" + }, + "default_plan": { + "type": "string", + "description": "Name of the plan the back-end uses for billing in case \n1. the user has not subscribed to a specific plan\n (see `default_plan` in `GET /me`) and\n2. also did not provide a specific plan with the\n processing request.\n\nIf a free plan is available at the back-end, it is \nprobably most useful to provide this as the back-end\nwide default plan and override it with paid plans through\nthe user-specific default plan in `GET /me`.\nOtherwise, users that have not set up payment yet MAY\nreceive an error for each processing requests where\nthey did not provide a free plan specifically.", + "example": "free" + }, + "plans": { + "description": "Array of plans", + "type": "array", + "items": { + "title": "Billing Plan", + "type": "object", + "required": [ + "name", + "description", + "paid" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of the plan. It MUST be accepted in a *case insensitive* manner throughout the API.", + "example": "free" + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "A description that gives a rough overview over the plan.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", + "example": "Free plan for testing." + }, + "paid": { + "type": "boolean", + "description": "Indicates whether the plan is a paid plan (`true`) or a free plan (`false`)." + }, + "url": { + "type": "string", + "description": "URL to a web page with more details about the plan.", + "format": "uri", + "example": "https://cloud.example/plans/free-plan" + } + } + }, + "example": [ + { + "name": "free", + "description": "Free plan. Calculates one tile per second and a maximum amount of 100 tiles per hour.", + "url": "https://cloud.example/plans/free-plan", + "paid": false + }, + { + "name": "premium", + "description": "Premium plan. Calculates unlimited tiles and each calculated tile costs 0.003 USD.", + "url": "https://cloud.example/plans/premium-plan", + "paid": true + } + ] + } + } + }, + "links": { + "description": "Links related to this service, e.g. the homepage of\nthe service provider or the terms of service.\n\nIt is highly RECOMMENDED to provide links with the\nfollowing `rel` (relation) types:\n\n1. `version-history`: A link back to the Well-Known URL\n(including `/.well-known/openeo`, see the corresponding endpoint for details)\nto allow clients to work on the most recent version.\n\n2. `terms-of-service`: A link to the terms of service. If\na back-end provides a link to the terms of service, the\nclients MUST provide a way to read the terms of service\nand only connect to the back-end after the user agreed to\nthem. The user interface MUST be designed in a way that\nthe terms of service are not agreed to by default, i.e.\nthe user MUST explicitly agree to them.\n\n3. `privacy-policy`: A link to the privacy policy (GDPR).\nIf a back-end provides a link to a privacy policy, the\nclients MUST provide a way to read the privacy policy and\nonly connect to the back-end after the user agreed to\nthem. The user interface MUST be designed in a way that\nthe privacy policy is not agreed to by default, i.e. the\nuser MUST explicitly agree to them.\n\n4. `service-desc` or `service-doc`: A link to the API definition.\nUse `service-desc` for machine-readable API definition and \n`service-doc` for human-readable API definition.\nRequired if full OGC API compatibility is desired.\n\n5. `conformance`: A link to the Conformance declaration\n(see `/conformance`). \nRequired if full OGC API compatibility is desired.\n\n6. `data`: A link to the collections (see `/collections`).\nRequired if full OGC API compatibility is desired.\n\n7. `create-form`: A link to a user registration page.\n\n8. `recovery-form`: A link to a page where a user can\nrecover a user account (e.g. to reset the password or send\na reminder about the username to the user's email account).\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "href": "https://cloud.example", + "rel": "about", + "type": "text/html", + "title": "Homepage of the service provider" + }, + { + "href": "https://cloud.example/tos", + "rel": "terms-of-service", + "type": "text/html", + "title": "Terms of Service" + }, + { + "href": "https://cloud.example/privacy", + "rel": "privacy-policy", + "type": "text/html", + "title": "Privacy Policy" + }, + { + "href": "https://cloud.example/register", + "rel": "create-form", + "type": "text/html", + "title": "User Registration" + }, + { + "href": "https://cloud.example/lost-password", + "rel": "recovery-form", + "type": "text/html", + "title": "Reset Password" + }, + { + "href": "https://cloud.example/.well-known/openeo", + "rel": "version-history", + "type": "application/json", + "title": "List of supported openEO versions" + }, + { + "href": "https://cloud.example/api/v1/conformance", + "rel": "conformance", + "type": "application/json", + "title": "OGC Conformance Classes" + }, + { + "href": "https://cloud.example/api/v1/collections", + "rel": "data", + "type": "application/json", + "title": "List of Datasets" + } + ] + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/.well-known/openeo": { + "get": { + "summary": "Supported openEO versions", + "operationId": "connect", + "description": "Lists all implemented openEO versions supported by the\nservice provider. This endpoint is the Well-Known URI\n(see [RFC 5785](https://www.rfc-editor.org/rfc/rfc5785.html)) for openEO.\n\nThis allows a client to easily identify the most recent openEO\nimplementation it supports. By default, a client SHOULD connect to the\nmost recent production-ready version it supports. If not available, the\nmost recent supported version of *all* versions SHOULD be connected to.\nClients MAY let users choose to connect to versions that are not\nproduction-ready or outdated.\nThe most recent version is determined by comparing the version numbers\naccording to rules from [Semantic Versioning](https://semver.org/),\nespecially [\u00a711](https://semver.org/#spec-item-11). Any pair of API\nversions in this list MUST NOT be equal according to Semantic Versioning.\n\nThe Well-Known URI is the entry point for clients and users, so make\nsure it is permanent and easy to use and remember. Clients MUST NOT\nrequire the well-known path (`/.well-known/openeo`) in the URL that is\nspecified by a user to connect to the back-end.\n\nFor clients, the usual behavior SHOULD follow these steps:\n1. The user provides a URI, which may consist of a scheme (protocol), \n an authority (host, port) and a path.\n2. The client parses the URI and appends `/.well-knwon/openeo` to the\n path. Make sure to correctly handle leading/trailing slashes.\n3. Send a request to the new URI.\n A. On success: Detect the most suitable API instance/version (see above)\n and read the [capabilites](#tag/Capabilities/operation/capabilities)\n from there.\n B. On failure: Directly try to read the capabilities from the original URI\n given by the user.\n\n**This URI MUST NOT be versioned as the other endpoints.**\nIf your API is available at `https://openeo.example/api/v1`, and\nyou instruct your API users to use `https://openeo.example` as connection URI, \nthe Well-Known URI SHOULD be located at `https://openeo.example/.well-known/openeo`.\nThe Well-Known URI is usually directly located at the top-level, but it is not a\nrequirement. For example, `https://openeo.example/eo/.well-known/openeo` is also allowed.\n\nClients MAY get additional information (e.g. title or description) about\na back-end from the most recent version that has the `production` flag\nset to `true`.", + "tags": [ + "Capabilities" + ], + "security": [ + {} + ], + "servers": [ + { + "url": "https://openeo-dev.eodc.eu/", + "description": "The Well-Known URI SHOULD be available directly at `https://{{domain}}/.well-known/openeo` in contrast to the other endpoints, which may be versioned and can run on other hosts, ports, ... etc." + } + ], + "responses": { + "200": { + "description": "List of all available API instances, each with URL and the implemented openEO API version.", + "content": { + "application/json": { + "schema": { + "title": "Well Known Discovery", + "type": "object", + "required": [ + "versions" + ], + "properties": { + "versions": { + "type": "array", + "items": { + "title": "API Instance", + "type": "object", + "required": [ + "url", + "api_version" + ], + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "*Absolute* URLs to the service.", + "example": "https://openeo.example/api/v1" + }, + "production": { + "$ref": "#/components/schemas/production" + }, + "api_version": { + "type": "string", + "description": "Version number of the openEO specification this back-end implements." + } + } + } + } + } + }, + "example": { + "versions": [ + { + "url": "https://openeo.example/api/v0", + "api_version": "0.5.1" + }, + { + "url": "https://openeo.example/api/v1", + "api_version": "1.2.0" + }, + { + "url": "https://dev.openeo.example/api/v2", + "production": false, + "api_version": "2.0.0-beta" + } + ] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/file_formats": { + "get": { + "summary": "Supported file formats", + "operationId": "list-file-types", + "description": "Lists supported input and output file formats.\n*Input* file formats specify which file a back-end can *read* from.\n*Output* file formats specify which file a back-end can *write* to.\n\nThe response to this request is an object listing all available input\nand output file formats separately with their parameters and additional\ndata. This endpoint does not include the supported secondary web\nservices.\n\n**Note**: Format names and parameters MUST be fully aligned with the\nGDAL codes if available, see [GDAL Raster\nFormats](https://gdal.org/drivers/raster/index.html) and [OGR Vector\nFormats](https://gdal.org/drivers/vector/index.html). It is OPTIONAL to\nsupport all output format parameters supported by GDAL. Some file\nformats not available through GDAL may be defined centrally for openEO.\nCustom file formats or parameters MAY be defined.\n\nThe format descriptions must describe how the file formats relate to \ndata cubes. Input file formats must describe how the files have to be\nstructured to be transformed into data cubes. Output file formats must\ndescribe how the data cubes are stored at the back-end and how the \nresulting file structure looks like.\n\nBack-ends MUST NOT support aliases, for example it is not allowed to\nsupport `geotiff` instead of `gtiff`. Nevertheless, openEO Clients MAY\ntranslate user input input for convenience (e.g. translate `geotiff` to\n`gtiff`). Also, for a better user experience the back-end can specify a\n`title`.\n\nFormat names MUST be accepted in a *case insensitive* manner throughout the API.", + "tags": [ + "Capabilities", + "Data Processing" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "An object with containing all input and output format separately. For each property `input` and `output` an object is defined where the file format names are the property keys and the property values are objects that define a title, supported parameters and related links.", + "content": { + "application/json": { + "schema": { + "title": "File Formats", + "type": "object", + "required": [ + "input", + "output" + ], + "properties": { + "input": { + "title": "Input File Formats", + "type": "object", + "description": "Map of supported input file formats, i.e. file formats a back-end can **read** from. The property keys are the file format names that are used by clients and users, for example in process graphs.", + "additionalProperties": { + "$ref": "#/components/schemas/file_format" + } + }, + "output": { + "title": "Output File Formats", + "type": "object", + "description": "Map of supported output file formats, i.e. file formats a back-end can **write** to. The property keys are the file format names that are used by clients and users, for example in process graphs.", + "additionalProperties": { + "$ref": "#/components/schemas/file_format" + } + } + } + }, + "example": { + "output": { + "GTiff": { + "title": "GeoTiff", + "description": "Export to GeoTiff. Doesn't support cloud-optimized GeoTiffs (COGs) yet.", + "gis_data_types": [ + "raster" + ], + "parameters": { + "tiled": { + "type": "boolean", + "description": "This option can be used to force creation of tiled TIFF files [true]. By default [false] stripped TIFF files are created.", + "default": false + }, + "compress": { + "type": "string", + "description": "Set the compression to use.", + "default": "NONE", + "enum": [ + "JPEG", + "LZW", + "DEFLATE", + "NONE" + ] + }, + "jpeg_quality": { + "type": "integer", + "description": "Set the JPEG quality when using JPEG.", + "minimum": 1, + "maximum": 100, + "default": 75 + } + }, + "links": [ + { + "href": "https://gdal.org/drivers/raster/gtiff.html", + "rel": "about", + "title": "GDAL on the GeoTiff file format and storage options" + } + ] + }, + "GPKG": { + "title": "OGC GeoPackage", + "gis_data_types": [ + "raster", + "vector" + ], + "parameters": { + "version": { + "type": "string", + "description": "Set GeoPackage version. In AUTO mode, this will be equivalent to 1.2 starting with GDAL 2.3.", + "enum": [ + "auto", + "1", + "1.1", + "1.2" + ], + "default": "auto" + } + }, + "links": [ + { + "href": "https://gdal.org/drivers/raster/gpkg.html", + "rel": "about", + "title": "GDAL on GeoPackage for raster data" + }, + { + "href": "https://gdal.org/drivers/vector/gpkg.html", + "rel": "about", + "title": "GDAL on GeoPackage for vector data" + } + ] + } + }, + "input": { + "GPKG": { + "title": "OGC GeoPackage", + "gis_data_types": [ + "raster", + "vector" + ], + "parameters": { + "table": { + "type": "string", + "description": "**RASTER ONLY.** Name of the table containing the tiles. If the GeoPackage dataset only contains one table, this option is not necessary. Otherwise, it is required." + } + }, + "links": [ + { + "href": "https://gdal.org/drivers/raster/gpkg.html", + "rel": "about", + "title": "GDAL on GeoPackage for raster data" + }, + { + "href": "https://gdal.org/drivers/vector/gpkg.html", + "rel": "about", + "title": "GDAL on GeoPackage for vector data" + } + ] + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/conformance": { + "get": { + "summary": "Conformance classes this API implements", + "operationId": "conformance", + "description": "Lists all conformance classes specified in various standards that the\nimplementation conforms to. Conformance classes are commonly used in\nall OGC APIs and the STAC API specification. openEO adds relatively\nbroadly defined conformance classes, especially for the extensions.\nOtherwise, the implemented functionality can usually be retrieved from\nthe [capabilties](#tag/Capabilities/operation/capabilities) in openEO.\n\nThe general openEO conformance class is `https://api.openeo.org/1.2.0`.\nSee the individual openEO API extensions for their conformance classes.\n\nThe conformance classes listed at this endpoint and listed in the \ncorresponding `conformsTo` property in `GET /` MUST be equal.\n\nMore details:\n- [STAC API](https://github.com/radiantearth/stac-api-spec), especially the conformance class \"STAC API - Collections\"\n- [OGC APIs](https://ogcapi.ogc.org/)", + "tags": [ + "Capabilities" + ], + "responses": { + "200": { + "description": "The URIs of all conformance classes supported by the server.", + "content": { + "application/json": { + "schema": { + "title": "OGC Conformance Classes", + "type": "object", + "required": [ + "conformsTo" + ], + "properties": { + "conformsTo": { + "$ref": "#/components/schemas/conformsTo" + } + } + } + } + } + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/collections": { + "get": { + "summary": "Basic metadata for all datasets", + "operationId": "list-collections", + "description": "Lists available collections with at least the required information.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting larger optional values from the objects in `collections` (e.g. the\n`summaries` and `cube:dimensions` properties).\nTo get the full metadata for a collection clients MUST\nrequest `GET /collections/{collection_id}`.\n\nThis endpoint is compatible with [STAC API 0.9.0 and later](https://stacspec.org) and\n[OGC API - Features 1.0](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html).\n[STAC API extensions](https://stac-api-extensions.github.io) and\n[STAC extensions](https://stac-extensions.github.io)\ncan be implemented in addition to what is documented here.\n\nNote: Although it is possible to request public collections without\nauthorization, it is RECOMMENDED that clients (re-)request the collections\nwith the Bearer token once available to also retrieve any private collections.", + "tags": [ + "EO Data Discovery" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Lists of collections and related links.", + "content": { + "application/json": { + "schema": { + "title": "Collections", + "type": "object", + "required": [ + "collections", + "links" + ], + "properties": { + "collections": { + "type": "array", + "items": { + "$ref": "#/components/schemas/collection" + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + }, + "example": { + "collections": [ + { + "stac_version": "1.0.0", + "type": "Collection", + "id": "Sentinel-2A", + "title": "Sentinel-2A MSI L1C", + "description": "Sentinel-2A is a wide-swath, high-resolution, multi-spectral imaging mission supporting Copernicus Land Monitoring studies, including the monitoring of vegetation, soil and water cover, as well as observation of inland waterways and coastal areas.", + "license": "proprietary", + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -56, + 180, + 83 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2015-06-23T00:00:00Z", + "2019-01-01T00:00:00Z" + ] + ] + } + }, + "keywords": [ + "copernicus", + "esa", + "msi", + "sentinel" + ], + "providers": [ + { + "name": "European Space Agency (ESA)", + "roles": [ + "producer", + "licensor" + ], + "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" + }, + { + "name": "openEO", + "roles": [ + "host" + ], + "url": "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2" + } + ], + "links": [ + { + "rel": "license", + "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf" + } + ] + }, + { + "stac_version": "1.0.0", + "type": "Collection", + "id": "MOD09Q1", + "title": "MODIS/Terra Surface Reflectance 8-Day L3 Global 250m SIN Grid V006", + "description": "The MOD09Q1 Version 6 product provides an estimate of the surface spectral reflectance of Terra MODIS Bands 1-2 corrected for atmospheric conditions such as gasses, aerosols, and Rayleigh scattering. Provided along with the two 250 m MODIS bands is one additional layer, the Surface Reflectance QC 250 m band. For each pixel, a value is selected from all the acquisitions within the 8-day composite period. The criteria for the pixel choice include cloud and solar zenith. When several acquisitions meet the criteria the pixel with the minimum channel 3 (blue) value is used. Validation at stage 3 has been achieved for all MODIS Surface Reflectance products.", + "license": "proprietary", + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -90, + 180, + 90 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2000-02-01T00:00:00Z", + null + ] + ] + } + }, + "links": [ + { + "rel": "license", + "href": "https://openeo.example/api/v1/collections/MOD09Q1/license" + } + ] + } + ], + "links": [ + { + "rel": "alternate", + "href": "https://openeo.example/csw", + "title": "openEO catalog (OGC Catalogue Services 3.0)" + } + ] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/collections/{collection_id}": { + "get": { + "summary": "Full metadata for a specific dataset", + "operationId": "describe-collection", + "description": "Lists **all** information about a specific collection specified by the\nidentifier `collection_id`.\n\nThis endpoint is compatible with [STAC API 0.9.0 and later](https://stacspec.org) and\n[OGC API - Features 1.0](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html).\n[STAC API extensions](https://stac-api-extensions.github.io) and\n[STAC extensions](https://stac-extensions.github.io)\ncan be implemented in addition to what is documented here.\n\nNote: Providing the Bearer token is REQUIRED for private collections.", + "tags": [ + "EO Data Discovery" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/collection_id" + } + ], + "responses": { + "200": { + "description": "JSON object with the full collection metadata.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "cube:dimensions", + "summaries" + ], + "allOf": [ + { + "$ref": "#/components/schemas/collection" + } + ] + }, + "example": { + "stac_version": "1.0.0", + "stac_extensions": [ + "https://stac-extensions.github.io/datacube/v2.2.0/schema.json" + ], + "type": "Collection", + "id": "Sentinel-2", + "title": "Sentinel-2 MSI L2A", + "description": "Sentinel-2A is a wide-swath, high-resolution, multi-spectral imaging mission supporting Copernicus Land Monitoring studies.", + "license": "proprietary", + "keywords": [ + "copernicus", + "esa", + "msi", + "sentinel" + ], + "providers": [ + { + "name": "European Space Agency (ESA)", + "roles": [ + "producer", + "licensor" + ], + "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" + }, + { + "name": "Google", + "roles": [ + "host" + ], + "url": "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2" + } + ], + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -56, + 180, + 83 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2015-06-23T00:00:00Z", + null + ] + ] + } + }, + "links": [ + { + "rel": "license", + "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf", + "type": "application/pdf" + }, + { + "rel": "http://www.opengis.net/def/rel/ogc/1.0/queryables", + "href": "https://openeo.example/api/v1/collections/Sentinel-2A/queryables", + "type": "application/schema+json" + }, + { + "rel": "about", + "href": "https://earth.esa.int/web/sentinel/user-guides/sentinel-2-msi/product-types/level-1c", + "type": "text/html", + "title": "ESA Sentinel-2 MSI Level-1C User Guide" + }, + { + "rel": "example", + "href": "https://openeo.example/api/v1/collections/Sentinel-2/examples/true-color.json", + "type": "application/json", + "title": "Example Process for True-Color Visualization" + }, + { + "rel": "example", + "href": "https://openeo.example/api/v1/collections/Sentinel-2/examples/ndvi.json", + "type": "application/json", + "title": "Example Process for NDVI Calculation and Visualization" + } + ], + "cube:dimensions": { + "x": { + "type": "spatial", + "axis": "x", + "extent": [ + -180, + 180 + ], + "reference_system": 4326 + }, + "y": { + "type": "spatial", + "axis": "y", + "extent": [ + -56, + 83 + ], + "reference_system": 4326 + }, + "t": { + "type": "temporal", + "extent": [ + "2015-06-23T00:00:00Z", + null + ], + "step": null + }, + "bands": { + "type": "bands", + "values": [ + "B1", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B8A", + "B9", + "B10", + "B11", + "B12" + ] + } + }, + "summaries": { + "constellation": [ + "Sentinel-2" + ], + "platform": [ + "Sentinel-2A", + "Sentinel-2B" + ], + "instruments": [ + "MSI" + ], + "eo:cloud_cover": { + "minimum": 0, + "maximum": 75 + }, + "sat:orbit_state": [ + "ascending", + "descending" + ], + "gsd": [ + 10, + 20, + 60 + ], + "eo:bands": [ + { + "name": "B1", + "common_name": "coastal", + "center_wavelength": 0.4439, + "gsd": 60 + }, + { + "name": "B2", + "common_name": "blue", + "center_wavelength": 0.4966, + "gsd": 10 + }, + { + "name": "B3", + "common_name": "green", + "center_wavelength": 0.56, + "gsd": 10 + }, + { + "name": "B4", + "common_name": "red", + "center_wavelength": 0.6645, + "gsd": 10 + }, + { + "name": "B5", + "center_wavelength": 0.7039, + "gsd": 20 + }, + { + "name": "B6", + "center_wavelength": 0.7402, + "gsd": 20 + }, + { + "name": "B7", + "center_wavelength": 0.7825, + "gsd": 20 + }, + { + "name": "B8", + "common_name": "nir", + "center_wavelength": 0.8351, + "gsd": 10 + }, + { + "name": "B8A", + "common_name": "nir08", + "center_wavelength": 0.8648, + "gsd": 20 + }, + { + "name": "B9", + "common_name": "nir09", + "center_wavelength": 0.945, + "gsd": 60 + }, + { + "name": "B10", + "common_name": "cirrus", + "center_wavelength": 1.3735, + "gsd": 60 + }, + { + "name": "B11", + "common_name": "swir16", + "center_wavelength": 1.6137, + "gsd": 20 + }, + { + "name": "B12", + "common_name": "swir22", + "center_wavelength": 2.2024, + "gsd": 20 + } + ], + "proj:epsg": { + "minimum": 32601, + "maximum": 32660 + } + }, + "assets": { + "thumbnail": { + "href": "https://openeo.example/api/v1/collections/Sentinel-2/thumbnail.png", + "type": "image/png", + "title": "Preview", + "roles": [ + "thumbnail" + ] + }, + "inspire": { + "href": "https://openeo.example/api/v1/collections/Sentinel-2/inspire.xml", + "type": "application/xml", + "title": "INSPIRE metadata", + "description": "INSPIRE compliant XML metadata", + "roles": [ + "metadata" + ] + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/collections/{collection_id}/queryables": { + "get": { + "summary": "Metadata filters for a specific dataset", + "operationId": "list-collection-queryables", + "description": "Lists **all** supported metadata filters (also called \"queryables\") for\na specific collection.\n\nThis endpoint is compatible with endpoint defined in the STAC API extension\n[`filter`](https://github.com/stac-api-extensions/filter#queryables) and\n[OGC API - Features - Part 3: Filtering](https://github.com/opengeospatial/ogcapi-features/tree/master/extensions/filtering).\nFor a precise definition please follow those specifications.\n\nThis endpoints provides a JSON Schema for each queryable that openEO\nusers can use in multiple scenarios:\n1. For loading data from the collection, e.g. in the process `load_collection`.\n2. For filtering items using CQL2 on the `/collections/{collection_id}/items` endpoint\n (if [STAC API - Features is implemented in addition to the openEO API](#tag/EO-Data-Discovery/STAC)).\n\nNote: Providing the Bearer token is REQUIRED for private collections.", + "tags": [ + "EO Data Discovery" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/collection_id" + } + ], + "responses": { + "200": { + "description": "A JSON Schema defining the queryables.\n\nIt is RECOMMENDED to dereference all \"$refs\".", + "content": { + "application/schema+json": { + "schema": { + "$ref": "#/components/schemas/json_schema" + }, + "example": { + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://openeo.example/api/v1/collections/Sentinel-2A/queryables", + "type": "object", + "title": "Sentinel 2A", + "properties": { + "eo:cloud_cover": { + "title": "Cloud Cover", + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "platform": { + "title": "Platform", + "description": "The satellite platform.", + "type": "string", + "enum": [ + "sentinel-2a", + "sentinel-2b" + ] + } + }, + "additionalProperties": false + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/processes": { + "get": { + "summary": "Supported predefined processes", + "operationId": "list-processes", + "description": "Lists all predefined processes and returns detailed process descriptions, including parameters and return values.", + "tags": [ + "Process Discovery" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Formal specification describing the supported predefined processes.", + "content": { + "application/json": { + "schema": { + "title": "Processes", + "type": "object", + "required": [ + "processes", + "links" + ], + "properties": { + "processes": { + "type": "array", + "items": { + "title": "Predefined Process", + "description": "A predefined process made available by the back-end.", + "type": "object", + "required": [ + "id", + "description", + "parameters", + "returns" + ], + "allOf": [ + { + "$ref": "#/components/schemas/process" + } + ] + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + }, + "example": { + "processes": [ + { + "id": "apply", + "summary": "Apply a process to each pixel", + "description": "Applies a *unary* process to each pixel value in the data cube (i.e. a local operation). A unary process takes a single value and returns a single value, for example ``abs()`` or ``linear_scale_range()``.", + "categories": [ + "cubes" + ], + "parameters": [ + { + "name": "data", + "description": "A data cube.", + "schema": { + "type": "object", + "subtype": "datacube" + } + }, + { + "name": "process", + "description": "A unary process to be applied on each value, may consist of multiple sub-processes.", + "schema": { + "type": "object", + "subtype": "process-graph", + "parameters": [ + { + "name": "x", + "description": "The value to process.", + "schema": { + "description": "Any data type." + } + } + ] + } + } + ], + "returns": { + "description": "A data cube with the newly computed values. The resolution, cardinality and the number of dimensions are the same as for the original data cube.", + "schema": { + "type": "object", + "subtype": "datacube" + } + } + }, + { + "id": "multiply", + "summary": "Multiplication of two numbers", + "description": "Multiplies the two numbers `x` and `y` (*x * y*) and returns the computed product.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", + "categories": [ + "math" + ], + "parameters": [ + { + "name": "x", + "description": "The multiplier.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + { + "name": "y", + "description": "The multiplicand.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The computed product of the two numbers.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + "exceptions": { + "MultiplicandMissing": { + "message": "Multiplication requires at least two numbers." + } + }, + "examples": [ + { + "arguments": { + "x": 5, + "y": 2.5 + }, + "returns": 12.5 + }, + { + "arguments": { + "x": -2, + "y": -4 + }, + "returns": 8 + }, + { + "arguments": { + "x": 1, + "y": null + }, + "returns": null + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/Product.html", + "title": "Product explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/8766229", + "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" + } + ] + } + ], + "links": [ + { + "rel": "alternate", + "href": "https://openeo.example/processes", + "type": "text/html", + "title": "HTML version of the processes" + } + ] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/udf_runtimes": { + "get": { + "summary": "Supported UDF runtimes", + "operationId": "list-udf-runtimes", + "description": "Lists the supported runtimes for user-defined functions (UDFs), which includes either the programming languages including version numbers and available libraries including version numbers or docker containers.", + "tags": [ + "Capabilities" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Description of UDF runtime support", + "content": { + "application/json": { + "schema": { + "title": "UDF Runtimes", + "type": "object", + "description": "Map of available runtime environments. Runtime environments\ncan be either a programming language environment or Docker-based.\n\nEach runtime environment has a unique name, which is used as\nthe property key. The name is used in processes to select the\nruntime environment for UDFs, so the names should be stable and\nmeaningful.\nIt is RECOMMENDED to use the following naming and casing:\n* For programming langauge environments use the names as provided\n in in the [Scriptol List of Programming Languages](https://www.scriptol.com/programming/list-programming-languages.php).\n* For docker images use the docker image identifier excluding the registry path.", + "additionalProperties": { + "x-additionalPropertiesName": "UDF Runtime name", + "allOf": [ + { + "$ref": "#/components/schemas/udf_runtime" + } + ] + } + }, + "example": { + "PHP": { + "title": "PHP v7.x", + "description": "Just an example how to reference a docker image.", + "experimental": true, + "type": "docker", + "docker": "openeo/udf-php7", + "default": "latest", + "tags": [ + "latest", + "7.3.1", + "7.3", + "7.2" + ], + "links": [ + { + "href": "https://hub.docker.com/openeo/udf-php7/", + "rel": "about" + } + ] + }, + "R": { + "title": "R v3.x for Statistical Computing", + "description": "R programming language with `Rcpp` and `rmarkdown` extensions installed.", + "type": "language", + "default": "3.5.2", + "versions": { + "3.1.0": { + "deprecated": true, + "libraries": { + "Rcpp": { + "version": "1.0.10", + "links": [ + { + "href": "https://cran.r-project.org/web/packages/Rcpp/index.html", + "rel": "about" + } + ] + }, + "rmarkdown": { + "version": "1.7.0", + "links": [ + { + "href": "https://cran.r-project.org/web/packages/rmarkdown/index.html", + "rel": "about" + } + ] + } + } + }, + "3.5.2": { + "libraries": { + "Rcpp": { + "version": "1.2.0", + "links": [ + { + "href": "https://cran.r-project.org/web/packages/Rcpp/index.html", + "rel": "about" + } + ] + }, + "rmarkdown": { + "version": "1.7.0", + "links": [ + { + "href": "https://cran.r-project.org/web/packages/rmarkdown/index.html", + "rel": "about" + } + ] + } + } + } + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/credentials/oidc": { + "get": { + "summary": "OpenID Connect authentication", + "operationId": "authenticate-oidc", + "description": "Lists the supported [OpenID Connect](http://openid.net/connect/)\nproviders (OP). OpenID Connect Providers MUST support [OpenID Connect\nDiscovery](http://openid.net/specs/openid-connect-discovery-1_0.html).\n\nIt is highly RECOMMENDED to implement OpenID Connect for public services\nin favor of Basic authentication.\n\nopenEO clients MUST use the **access token** as part of the Bearer token\nfor authorization in subsequent API calls (see also the information\nabout Bearer tokens in this document). Clients MUST NOT use the id token\nor the authorization code. The access token provided by an OpenID Connect\nProvider does not necessarily provide information about the issuer (i.e. the\nOpenID Connect provider) and therefore a prefix MUST be added to the Bearer\nToken sent in subsequent API calls to protected endpoints. The Bearer\nToken sent to protected endpoints MUST consist of the authentication\nmethod (here `oidc`), the provider ID and the access token itself. All\nseparated by a forward slash `/`. The provider ID corresponds to the\nvalue specified for `id` for each provider in the response body of this\nendpoint. The header in subsequent API calls for a provider with `id`\n`ms` would look as follows: `Authorization: Bearer oidc/ms/TOKEN`\n(replace `TOKEN` with the actual access token received from the OpenID\nConnect Provider).\n\nBack-ends MAY request user information ([including Claims](https://openid.net/specs/openid-connect-core-1_0.html#Claims))\nfrom the [OpenID Connect Userinfo endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)\nusing the access token (without the prefix described above). Therefore,\nboth openEO client and openEO back-end are relying parties (clients) to\nthe OpenID Connect Provider.", + "tags": [ + "Account Management" + ], + "security": [ + {} + ], + "responses": { + "200": { + "description": "Lists the the OpenID Connect Providers.", + "content": { + "application/json": { + "schema": { + "title": "OpenID Connect Providers", + "type": "object", + "required": [ + "providers" + ], + "properties": { + "providers": { + "type": "array", + "description": "The first provider in this list is the default provider for authentication. Clients can either pre-select or directly use the default provider for authentication if the user doesn't specify a specific value.", + "minItems": 1, + "items": { + "title": "OpenID Connect Provider", + "type": "object", + "required": [ + "id", + "issuer", + "title" + ], + "properties": { + "id": { + "type": "string", + "description": "A per-backend **unique** identifier for the OpenID Connect Provider to be as prefix for the Bearer token.", + "pattern": "[\\d\\w]{1,20}" + }, + "issuer": { + "type": "string", + "format": "uri", + "description": "The [issuer location](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig) (also referred to as 'authority' in some client libraries) is the URL of the OpenID Connect provider, which conforms to a set of rules:\n1. After appending `/.well-known/openid-configuration` to the URL, a [HTTP/1.1 GET request](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest) to the concatenated URL MUST return a [OpenID Connect Discovery Configuration Response](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). The response provides all information required to authenticate using OpenID Connect.\n2. The URL MUST NOT contain a terminating forward slash `/`.", + "example": "https://accounts.google.com" + }, + "scopes": { + "type": "array", + "description": "A list of OpenID Connect scopes that the client MUST at least include when requesting authorization. Clients MAY add additional scopes such as the `offline_access` scope to retrieve a refresh token.\nIf scopes are specified, the list MUST at least contain the `openid` scope.", + "items": { + "type": "string" + } + }, + "title": { + "type": "string", + "description": "The name that is publicly shown in clients for this OpenID Connect provider." + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "A description that explains how the authentication procedure works.\n\nIt should make clear how to register and get credentials. This should\ninclude instruction on setting up `client_id`, `client_secret` and `redirect_uri`.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich\ntext representation." + }, + "default_clients": { + "title": "Default OpenID Connect Clients", + "type": "array", + "description": "List of default OpenID Connect clients that can be used by an openEO client\nfor OpenID Connect based authentication.\n\nA default OpenID Connect client is managed by the back-end implementer.\nIt MUST be configured to be usable without a client secret,\nwhich limits its applicability to OpenID Connect grant types like\n\"Authorization Code Grant with PKCE\" and \"Device Authorization Grant with PKCE\"\n\nA default OpenID Connect client is provided without availability guarantees.\nThe back-end implementer CAN revoke, reset or update it any time.\nAs such, openEO clients SHOULD NOT store or cache default OpenID Connect client information\nfor long term usage.\nA default OpenID Connect client is intended to simplify authentication for novice users.\nFor production use cases, it is RECOMMENDED to set up a dedicated OpenID Connect client.", + "uniqueItems": true, + "items": { + "title": "Default OpenID Connect Client", + "type": "object", + "required": [ + "id", + "grant_types" + ], + "properties": { + "id": { + "type": "string", + "description": "The OpenID Connect Client ID to be used in the authentication procedure." + }, + "grant_types": { + "type": "array", + "description": "List of authorization grant types (flows) supported by the OpenID Connect client.\nA grant type descriptor consist of a OAuth 2.0 grant type,\nwith an additional `+pkce` suffix when the grant type should be used with\nthe PKCE extension as defined in [RFC 7636](https://www.rfc-editor.org/rfc/rfc7636.html).\n\nAllowed values:\n- `implicit`: Implicit Grant as specified in [RFC 6749, sec. 1.3.2](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.3.2)\n- `authorization_code` / `authorization_code+pkce`: Authorization Code Grant as specified in [RFC 6749, sec. 1.3.1](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.3.1), with or without PKCE extension.\n- `urn:ietf:params:oauth:grant-type:device_code` / `urn:ietf:params:oauth:grant-type:device_code+pkce`: Device Authorization Grant (aka Device Code Flow) as specified in [RFC 8628](https://www.rfc-editor.org/rfc/rfc8628.html), with or without PKCE extension. Note that the combination of this grant with the PKCE extension is *not standardized* yet.\n- `refresh_token`: Refresh Token as specified in [RFC 6749, sec. 1.5](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.5)", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "implicit", + "authorization_code", + "authorization_code+pkce", + "urn:ietf:params:oauth:grant-type:device_code", + "urn:ietf:params:oauth:grant-type:device_code+pkce", + "refresh_token" + ] + } + }, + "redirect_urls": { + "type": "array", + "description": "List of redirect URLs that are whitelisted by the OpenID Connect client.\nRedirect URLs MUST be provided when the OpenID Connect client supports\nthe Implicit Grant or the Authorization Code Grant (with or without PKCE extension).", + "uniqueItems": true, + "items": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "links": { + "type": "array", + "description": "Links related to this provider, for example a\nhelp page or a page to register a new user account.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } + } + } + } + } + } + }, + "example": { + "providers": [ + { + "id": "egi", + "issuer": "https://aai.egi.eu/oidc", + "title": "EGI (default)", + "description": "Login with your academic account.", + "scopes": [ + "openid", + "profile", + "email" + ], + "default_clients": [ + { + "id": "KStcUzD5AIUA", + "grant_types": [ + "implicit", + "authorization_code+pkce", + "urn:ietf:params:oauth:grant-type:device_code+pkce", + "refresh_token" + ], + "redirect_urls": [ + "https://editor.openeo.org/" + ] + } + ] + }, + { + "id": "google", + "issuer": "https://accounts.google.com", + "title": "Google", + "description": "Login with your Google Account.", + "scopes": [ + "openid", + "profile", + "email", + "earthengine" + ] + }, + { + "id": "ms", + "issuer": "https://login.microsoftonline.com/example-tenant/v2.0", + "title": "Microsoft", + "description": "Login with your Microsoft or Skype Account.", + "scopes": [] + } + ] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/credentials/basic": { + "get": { + "summary": "HTTP Basic authentication", + "operationId": "authenticate-basic", + "description": "Checks the credentials provided through [HTTP Basic Authentication according to RFC 7617](https://www.rfc-editor.org/rfc/rfc7617.html) and returns an access token for valid credentials.\n\nThe credentials (username and password) MUST be sent in the HTTP header `Authorization` with type `Basic` and the Base64 encoded string consisting of username and password separated by a double colon `:`. The header would look as follows for username `user` and password `pw`: `Authorization: Basic dXNlcjpwdw==`.\n\nThe access token has to be used in the Bearer token for authorization in subsequent API calls (see also the information about Bearer tokens in this document). The access token returned by this request MUST NOT be provided with `basic//` prefix, but the Bearer Token sent in subsequent API calls to protected endpoints MUST be prefixed with `basic//`. The header in subsequent API calls would look as follows: `Authorization: Bearer basic//TOKEN` (replace `TOKEN` with the actual access token).\n\nIt is RECOMMENDED to implement this authentication method for non-public services only.", + "tags": [ + "Account Management" + ], + "security": [ + { + "Basic": [] + } + ], + "responses": { + "200": { + "description": "Credentials are correct and authentication succeeded.", + "content": { + "application/json": { + "schema": { + "title": "HTTP Basic Access Token", + "type": "object", + "required": [ + "access_token" + ], + "properties": { + "access_token": { + "description": "The access token (without `basic//` prefix) to be used in the Bearer token for authorization in subsequent API calls.", + "type": "string", + "example": "b34ba2bdf9ac9ee1" + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/validation": { + "post": { + "summary": "Validate a user-defined process (graph)", + "operationId": "validate-custom-process", + "description": "Validates a user-defined process without executing it. A user-defined process is\nconsidered valid unless the `errors` array in the response contains at\nleast one error.\n\nChecks whether the process graph is schematically correct and the\nprocesses are supported by the back-end. It MUST also check the\narguments against the schema, but checking whether the arguments are\nadequate in the context of data is OPTIONAL. For example, a non-existing\nband name may get rejected only by a few back-ends.\nThe validation MUST NOT throw an error for unresolvable process parameters.\n\nBack-ends MUST validate the process graph. Validating the corresponding\nmetadata is OPTIONAL.\n\nErrors that usually occur during processing MAY NOT get reported, e.g.\nif a referenced file is accessible at the time of execution.\n\nBack-ends can either report all errors at once or stop the validation\nonce they found the first error. \n\nPlease note that a validation always returns with HTTP status code 200.\nError codes in the 4xx and 5xx ranges MUST be returned only when the\ngeneral validation request is invalid (e.g. server is busy or properties\nin the request body are missing), but never if an error was found during\nvalidation of the user-defined process (e.g. an unsupported process).", + "tags": [ + "Data Processing", + "User-Defined Processes" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Returns the validation result as a list of errors. An empty list indicates a successful validation.", + "content": { + "application/json": { + "schema": { + "title": "Validation Result", + "type": "object", + "required": [ + "errors" + ], + "properties": { + "errors": { + "description": "A list of validation errors.", + "type": "array", + "items": { + "$ref": "#/components/schemas/error" + } + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "examples": { + "evi_user_defined_process": { + "$ref": "#/components/examples/evi_user_defined_process" + } + } + } + }, + "description": "Specifies the user-defined process to be validated." + } + } + }, + "/result": { + "post": { + "summary": "Process and download data synchronously", + "operationId": "compute-result", + "description": "Executes a user-defined process directly (synchronously) and the result will be downloaded in the format specified in the process graph. This endpoint can be used to generate small previews or test user-defined processes before starting a batch job.\nTimeouts on either client- or server-side are to be expected for complex computations. Back-ends MAY send the openEO error `ProcessGraphComplexity` immediately if the computation is expected to time out. Otherwise requests MAY time-out after a certain amount of time by sending openEO error `RequestTimeout`.\nA header named `OpenEO-Costs` MAY be sent with all responses, which MUST include the costs for processing and downloading the data. Additionally, a link to a log file MAY be sent in the header.", + "tags": [ + "Data Processing" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Result data in the requested output format", + "headers": { + "Content-Type": { + "description": "The appropriate media (MIME) type for the requested output\nformat MUST be sent, if the response contains a single file.\n\nTo send multiple files at once it is RECOMMENDED to use the\n[`tar` file format](https://www.gnu.org/software/tar/manual/html_node/Standard.html)\n(media type: `application/x-tar`).\n\nTo mimic the results of batch jobs, it is RECOMMENDED that \n1. clients extract the tar file directly after receiving it so that users\n can directly work on the contained files *and*\n2. back-ends add STAC Items and/or Collections to the tar file\n so that users can make sense of the files.", + "schema": { + "type": "string" + } + }, + "OpenEO-Costs": { + "description": "MAY include the costs for processing and downloading the data.", + "schema": { + "$ref": "#/components/schemas/money" + } + }, + "Link": { + "description": "The header MAY indicate a link to a log file generated by the request. If provided, the link MUST be serialized according to [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288.html#section-3) and MUST use the relation type `monitor`. The link MUST follow the specifications for the links `GET /jobs/{job_id}/logs` and `GET /services/{service_id}/logs`, except that is MUST NOT accept any parameters (limit/offset). Therefore, the link MUST be accessible with HTTP GET, MUST be secured using a Bearer token and MUST follow the corresponding request body schema.", + "schema": { + "type": "string", + "pattern": "^<[^>]+>;\\s?rel=\"monitor\"", + "example": "; rel=\"monitor\"" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "description": "Specifies the job details, e.g. the user-defined process and billing details.", + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Synchronous Result Request", + "type": "object", + "required": [ + "process" + ], + "properties": { + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "budget": { + "$ref": "#/components/schemas/budget" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan_null_default" + }, + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" + } + }, + "additionalProperties": { + "description": "You can add additional back-end specific properties here." + } + } + } + } + } + } + }, + "/process_graphs": { + "get": { + "summary": "List all user-defined processes", + "operationId": "list-custom-processes", + "description": "Lists all user-defined processes (process graphs) of the\nauthenticated user that are stored at the back-end.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting larger optional values from the objects in `processes`\n(e.g. the `exceptions`, `examples` and `links` properties).\nTo get the full metadata for a user-defined process clients MUST\nrequest `GET /process_graphs/{process_graph_id}`.", + "tags": [ + "User-Defined Processes", + "Process Discovery" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "JSON array with user-defined processes.", + "content": { + "application/json": { + "schema": { + "title": "User-Defined Processes", + "type": "object", + "required": [ + "processes", + "links" + ], + "properties": { + "processes": { + "description": "Array of user-defined processes", + "type": "array", + "items": { + "$ref": "#/components/schemas/user_defined_process_meta" + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + }, + "example": { + "processes": [ + { + "id": "evi", + "summary": "Enhanced Vegetation Index", + "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", + "parameters": [ + { + "name": "red", + "description": "Value from the red band.", + "schema": { + "type": "number" + } + }, + { + "name": "blue", + "description": "Value from the blue band.", + "schema": { + "type": "number" + } + }, + { + "name": "nir", + "description": "Value from the near infrared band.", + "schema": { + "type": "number" + } + } + ], + "returns": { + "description": "Computed EVI.", + "schema": { + "type": "number" + } + } + }, + { + "id": "ndsi", + "summary": "Normalized-Difference Snow Index", + "parameters": [ + { + "name": "green", + "description": "Value from the Visible Green (0.53 - 0.61 micrometers) band.", + "schema": { + "type": "number" + } + }, + { + "name": "swir", + "description": "Value from the Short Wave Infrared (1.55 - 1.75 micrometers) band.", + "schema": { + "type": "number" + } + } + ], + "returns": { + "schema": { + "type": "number" + } + } + }, + { + "id": "my_custom_process" + } + ], + "links": [] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/process_graphs/{process_graph_id}": { + "parameters": [ + { + "name": "process_graph_id", + "in": "path", + "description": "Per-user unique identifier for a user-defined process.", + "required": true, + "schema": { + "$ref": "#/components/schemas/process_id" + } + } + ], + "get": { + "summary": "Full metadata for a user-defined process", + "operationId": "describe-custom-process", + "description": "Lists all information about a user-defined process, including its process graph.", + "tags": [ + "User-Defined Processes", + "Process Discovery" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "The user-defined process with process graph.", + "content": { + "application/json": { + "schema": { + "title": "User-Defined Process", + "description": "A user-defined process with processing instructions as process graph.", + "type": "object", + "required": [ + "process_graph" + ], + "allOf": [ + { + "$ref": "#/components/schemas/user_defined_process_meta" + } + ] + }, + "examples": { + "evi_user_defined_process": { + "$ref": "#/components/examples/evi_user_defined_process" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "put": { + "summary": "Store a user-defined process", + "operationId": "store-custom-process", + "description": "Stores a provided user-defined process with process graph that can be\nreused in other processes.\n\nIf a process with the specified `process_graph_id` exists, the process\nis fully replaced. The id can't be changed for existing user-defined\nprocesses. The id MUST be unique across its namespace.\n\nPartially updating user-defined processes is not supported.\n\nTo simplify exchanging user-defined processes, the property `id` can be part of\nthe request body. If the values don't match, the value for `id` gets\nreplaced with the value from the `process_graph_id` parameter in the\npath.", + "tags": [ + "User-Defined Processes" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "The user-defined process has been stored successfully." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "description": "Specifies the process graph with its meta data.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "examples": { + "evi_user_defined_process": { + "$ref": "#/components/examples/evi_user_defined_process" + } + } + } + } + } + }, + "delete": { + "summary": "Delete a user-defined process", + "operationId": "delete-custom-process", + "description": "Deletes the data related to this user-defined process, including its process graph.\n\nDoes NOT delete jobs or services that reference this user-defined process.", + "tags": [ + "User-Defined Processes" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "The user-defined process has been successfully deleted" + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/service_types": { + "get": { + "summary": "Supported secondary web service protocols", + "operationId": "list-service-types", + "description": "Lists supported secondary web service protocols such as\n[OGC WMS](http://www.opengeospatial.org/standards/wms),\n[OGC WCS](http://www.opengeospatial.org/standards/wcs),\n[OGC API - Features](https://www.ogc.org/standards/ogcapi-features)\nor [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).\nThe response is an object of all available secondary web service protocols\nwith their supported configuration settings and expected process parameters.\n\n* The configuration settings for the service SHOULD be defined upon\n creation of a service and the service will be set up accordingly.\n* The process parameters SHOULD be referenced (with a `from_parameter`\n reference) in the user-defined process that is used to compute web service\n results.\n The appropriate arguments MUST be provided to the user-defined process,\n usually at runtime from the context of the web service,\n For example, a map service such as a WMS would\n need to inject the spatial extent into the user-defined process so that the\n back-end can compute the corresponding tile correctly.\n\nTo improve interoperability between back-ends common names for the\nservices SHOULD be used, e.g. the abbreviations used in the official\n[OGC Schema Repository](http://schemas.opengis.net/) for the respective\nservices.\n\nService names MUST be accepted in a *case insensitive* manner throughout the API.", + "tags": [ + "Capabilities", + "Secondary Services" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "An object with a map containing all service names as keys and an object that defines supported configuration settings and process parameters.", + "content": { + "application/json": { + "schema": { + "title": "Service Types", + "type": "object", + "description": "Map of supported secondary web services.", + "additionalProperties": { + "x-additionalPropertiesName": "Service Name", + "title": "Service Type", + "type": "object", + "required": [ + "configuration", + "process_parameters" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/object_title" + }, + "description": { + "$ref": "#/components/schemas/description" + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "configuration": { + "title": "Service Configuration", + "description": "Map of supported configuration settings made available to the creator of the service.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/resource_parameter" + } + }, + "process_parameters": { + "title": "Process Parameters", + "description": "List of parameters made available to user-defined processes.", + "type": "array", + "items": { + "$ref": "#/components/schemas/process_parameter" + } + }, + "links": { + "description": "Links related to this service type, e.g. more\ninformation about the configuration settings and process parameters.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + } + } + } + } + }, + "example": { + "WMS": { + "title": "OGC Web Map Service", + "configuration": { + "version": { + "type": "string", + "description": "The WMS version offered to consumers of the service.", + "default": "1.3.0", + "enum": [ + "1.1.1", + "1.3.0" + ] + } + }, + "process_parameters": [ + { + "name": "layer", + "description": "The layer name.", + "schema": { + "type": "string" + }, + "default": "roads" + }, + { + "name": "spatial_extent", + "description": "A bounding box in WGS84.", + "schema": { + "type": "object", + "required": [ + "west", + "south", + "east", + "north" + ], + "properties": { + "west": { + "description": "West (lower left corner, coordinate axis 1).", + "type": "number" + }, + "south": { + "description": "South (lower left corner, coordinate axis 2).", + "type": "number" + }, + "east": { + "description": "East (upper right corner, coordinate axis 1).", + "type": "number" + }, + "north": { + "description": "North (upper right corner, coordinate axis 2).", + "type": "number" + } + } + } + } + ], + "links": [ + { + "href": "https://www.opengeospatial.org/standards/wms", + "rel": "about", + "title": "OGC Web Map Service Standard" + } + ] + }, + "OGCAPI-FEATURES": { + "title": "OGC API - Features", + "description": "Exposes a OGC API - Features in version 1.0 of the specification (successor of OGC WFS 3.0).", + "configuration": { + "title": { + "type": "string", + "description": "The title for the OGC API - Features landing page" + }, + "description": { + "type": "string", + "description": "The description for the OGC API - Features landing page" + }, + "conformsTo": { + "type": "array", + "description": "The OGC API - Features conformance classes to enable for this service.\n\n`http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core` is always enabled.", + "items": { + "type": "string", + "enum": [ + "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30", + "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/html", + "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson", + "http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs" + ] + } + } + }, + "process_parameters": [], + "links": [ + { + "href": "https://www.opengeospatial.org/standards/wfs", + "rel": "about", + "title": "OGC Web Feature Service Standard" + } + ] + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/services": { + "get": { + "summary": "List all web services", + "operationId": "list-services", + "description": "Lists all secondary web services submitted by a user.\n\nIt is **strongly RECOMMENDED** to keep the response size small by omitting\nall optional non-scalar values (i.e. arrays and objects) from objects in `services`\n(i.e. the `process`, `configuration` and `attributes` properties).\nTo get the full metadata for a secondary web service clients MUST\nrequest `GET /services/{service_id}`.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Array of secondary web service descriptions", + "content": { + "application/json": { + "schema": { + "title": "Secondary Web Services", + "type": "object", + "required": [ + "services", + "links" + ], + "properties": { + "services": { + "type": "array", + "items": { + "$ref": "#/components/schemas/service" + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "post": { + "summary": "Publish a new service", + "operationId": "create-service", + "description": "Creates a new secondary web service such as a\n[OGC WMS](http://www.opengeospatial.org/standards/wms),\n[OGC WCS](http://www.opengeospatial.org/standards/wcs),\n[OGC API - Features](https://www.ogc.org/standards/ogcapi-features)\nor [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).\n\nThe secondary web service SHOULD process the underlying\ndata on demand, based on process parameters provided to the\nuser-defined process (through `from_parameter` references) at run-time,\nfor example for the spatial/temporal extent, resolution, etc.\nThe available process parameters are specified per\nservice type at `GET /service_types`.\n\n**Note:** Costs incurred by shared secondary web services are usually\npaid by the owner, but this depends on the service type and whether it\nsupports charging fees or not.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "201": { + "description": "The service has been created successfully.", + "headers": { + "Location": { + "required": true, + "schema": { + "description": "Absolute URL to the newly created service.\n\nThe URL points to the metadata endpoint\n`GET /services/{service_id}` with the `{service_id}` being the\nunique identifier (ID) of the created service.\nMUST NOT point to the actual instance (e.g. WMTS base URL) of\nthe service. The URL to the instance is made available by the\nmetadata endpoint in the property `url`.", + "format": "uri", + "type": "string", + "example": "https://openeo.example/api/v1/services/123" + } + }, + "OpenEO-Identifier": { + "required": true, + "schema": { + "$ref": "#/components/schemas/service_id" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Store Secondary Web Service Request", + "type": "object", + "required": [ + "type", + "process" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/eo_title" + }, + "description": { + "$ref": "#/components/schemas/eo_description" + }, + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "type": { + "$ref": "#/components/schemas/service_type" + }, + "enabled": { + "allOf": [ + { + "$ref": "#/components/schemas/service_enabled" + }, + { + "default": true + } + ] + }, + "configuration": { + "$ref": "#/components/schemas/service_configuration" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan_null_default" + }, + "budget": { + "$ref": "#/components/schemas/budget" + }, + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" + } + }, + "additionalProperties": { + "description": "You can add additional back-end specific properties here." + } + } + } + }, + "description": "The base data for the secondary web service to create" + } + } + }, + "/services/{service_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/service_id" + } + ], + "patch": { + "summary": "Modify a service", + "operationId": "update-service", + "description": "Modifies an existing secondary web service at the back-end,\nbut maintain the identifier. Changes can be grouped in a single request.\n\nUser have to create a new service to change the service type.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "Changes to the service were applied successfully." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Update Secondary Web Service Request", + "type": "object", + "properties": { + "title": { + "$ref": "#/components/schemas/eo_title" + }, + "description": { + "$ref": "#/components/schemas/eo_description" + }, + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "enabled": { + "$ref": "#/components/schemas/service_enabled" + }, + "configuration": { + "$ref": "#/components/schemas/service_configuration" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan_null" + }, + "budget": { + "$ref": "#/components/schemas/budget_update" + }, + "log_level": { + "$ref": "#/components/schemas/min_log_level_update" + } + } + } + } + }, + "description": "The data to change for the specified secondary web service." + } + }, + "get": { + "summary": "Full metadata for a service", + "operationId": "describe-service", + "description": "Lists all information about a secondary web service.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Details of the created service", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "process", + "configuration", + "attributes" + ], + "allOf": [ + { + "$ref": "#/components/schemas/service" + } + ] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "delete": { + "summary": "Delete a service", + "operationId": "delete-service", + "description": "Deletes all data related to this secondary web service. Computations are stopped, computed results are deleted and access to this is not possible any more. This service won't generate additional costs.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "The service has been successfully deleted." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/services/{service_id}/logs": { + "get": { + "summary": "Logs for a secondary service", + "operationId": "debug-service", + "description": "Lists log entries for the secondary service, usually for debugging purposes.\nBack-ends can log any information that may be relevant for a user. Users can log information during data processing using respective processes such as `inspect`.\nIf requested consecutively while the secondary service is enabled, it is RECOMMENDED that clients use the offset parameter to get only the entries they have not received yet.\nWhile pagination itself is OPTIONAL, the `offset` parameter is REQUIRED to be implemented by back-ends.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/service_id" + }, + { + "$ref": "#/components/parameters/log_offset" + }, + { + "$ref": "#/components/parameters/log_level" + }, + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/logs" + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/jobs": { + "get": { + "summary": "List all batch jobs", + "operationId": "list-jobs", + "description": "Lists all batch jobs submitted by a user.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting all optional non-scalar values (i.e. arrays and objects) from\nobjects in `jobs` (i.e. the `process` property).\nTo get the full metadata for a job clients MUST request `GET /jobs/{job_id}`.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Array of job descriptions", + "content": { + "application/json": { + "schema": { + "title": "Batch Jobs", + "type": "object", + "required": [ + "jobs", + "links" + ], + "properties": { + "jobs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/batch_job" + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "post": { + "summary": "Create a new batch job", + "operationId": "create-job", + "description": "Creates a new batch processing task (job) from one or more (chained)\nprocesses at the back-end.\n\nProcessing the data doesn't start yet. The job status gets initialized\nas `created` by default.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "201": { + "description": "The batch job has been created successfully.", + "headers": { + "Location": { + "required": true, + "schema": { + "description": "Absolute URL to the newly created batch job.\n\nThe URL points to the metadata endpoint\n`GET /jobs/{job_id}` with the `{job_id}` being the\nunique identifier (ID) of the created batch job.", + "format": "uri", + "type": "string", + "example": "https://openeo.example/api/v1/jobs/123" + } + }, + "OpenEO-Identifier": { + "required": true, + "schema": { + "$ref": "#/components/schemas/job_id" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Store Batch Job Request", + "type": "object", + "required": [ + "process" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/eo_title" + }, + "description": { + "$ref": "#/components/schemas/eo_description" + }, + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan_null_default" + }, + "budget": { + "$ref": "#/components/schemas/budget" + }, + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" + } + }, + "additionalProperties": { + "description": "You can add additional back-end specific properties here." + } + } + } + }, + "description": "Specifies the job details, e.g. the user-defined process and billing details." + } + } + }, + "/jobs/{job_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/job_id" + } + ], + "patch": { + "summary": "Modify a batch job", + "operationId": "update-job", + "description": "Modifies an existing job at the back-end, but maintains the identifier.\nChanges can be grouped in a single request.\n\nThe job status does not change.\n\nJobs can only be modified when the job is not queued and not running.\nOtherwise, requests to this endpoint MUST be rejected with openEO error\n`JobLocked`.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "Changes to the job applied successfully." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Update Batch Job Request", + "type": "object", + "properties": { + "title": { + "$ref": "#/components/schemas/eo_title" + }, + "description": { + "$ref": "#/components/schemas/eo_description" + }, + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan_null" + }, + "budget": { + "$ref": "#/components/schemas/budget_update" + }, + "log_level": { + "$ref": "#/components/schemas/min_log_level_update" + } + } + } + } + }, + "description": "Specifies the job details to update." + } + }, + "get": { + "summary": "Full metadata for a batch job", + "operationId": "describe-job", + "description": "Lists all information about a submitted batch job.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Full job information.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "process" + ], + "allOf": [ + { + "$ref": "#/components/schemas/batch_job" + } + ] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "delete": { + "summary": "Delete a batch job", + "operationId": "delete-job", + "description": "Deletes all data related to this job. Computations are stopped and computed results are deleted. This job won't generate additional costs for processing.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "The job has been successfully deleted." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/jobs/{job_id}/estimate": { + "get": { + "summary": "Get an estimate for a batch job", + "operationId": "estimate-job", + "description": "Calculates an estimate for a batch job. Back-ends can decide to either calculate the duration, the costs, the size or a combination of them.\nBack-end providers MAY specify an expiry time for the estimate. Starting to process data afterwards MAY be charged at a higher cost. Costs do often not include download costs. Whether download costs are included or not can be indicated explicitly with the `downloads_included` flag.\nThe estimate SHOULD be the upper limit of the costs, but back-end are free to use the field according to their terms of service.\nFor some batch jobs it is not (easily) possible to estimate the costs reliably, e.g. if a UDF or ML model is part of the process. In this case, the server SHOULD return a `EstimateComplexity` error with HTTP status code 500.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/job_id" + } + ], + "responses": { + "200": { + "description": "The estimated costs with regard to money, processing time and storage capacity. At least one of `costs`, `duration` or `size` MUST be provided.", + "content": { + "application/json": { + "schema": { + "title": "Batch Job Estimate", + "type": "object", + "anyOf": [ + { + "required": [ + "costs" + ] + }, + { + "required": [ + "duration" + ] + }, + { + "required": [ + "size" + ] + } + ], + "properties": { + "costs": { + "$ref": "#/components/schemas/money" + }, + "duration": { + "type": "string", + "description": "Estimated duration for the operation. Duration MUST be specified as a ISO 8601 duration.", + "example": "P1Y2M10DT2H30M" + }, + "size": { + "type": "integer", + "description": "Estimated required storage capacity, i.e. the size of the generated files. Size MUST be specified in bytes.", + "example": 157286400 + }, + "downloads_included": { + "type": "integer", + "nullable": true, + "description": "Specifies how many full downloads of the processed data are included in the estimate. Set to `null` for unlimited downloads, which is also the default value.", + "example": 5, + "default": null + }, + "expires": { + "type": "string", + "format": "date-time", + "description": "Time until which the estimate is valid, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2020-11-01T00:00:00Z" + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/jobs/{job_id}/logs": { + "get": { + "summary": "Logs for a batch job", + "operationId": "debug-job", + "description": "Lists log entries for the batch job, usually for debugging purposes.\n\nBack-ends can log any information that may be relevant for a user\nat any stage (status) of the batch job.\nUsers can log information during data processing using respective\nprocesses such as `inspect`.\n\nIf requested consecutively, it is RECOMMENDED that clients use the offset\nparameter to get only the entries they have not received yet.\n\nWhile pagination itself is OPTIONAL, the `offset` parameter is REQUIRED\nto be implemented by back-ends.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/job_id" + }, + { + "$ref": "#/components/parameters/log_offset" + }, + { + "$ref": "#/components/parameters/log_level" + }, + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/logs" + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/jobs/{job_id}/results": { + "parameters": [ + { + "$ref": "#/components/parameters/job_id" + } + ], + "get": { + "summary": "List batch job results", + "operationId": "list-results", + "description": "Lists signed URLs pointing to the processed files, usually after the batch job\nhas finished. Back-ends may also point to intermediate results after the\njob has stopped due to an error or if the `partial` parameter has been set.\n\nThe response includes additional metadata. It is a valid\n[STAC Item](https://github.com/radiantearth/stac-spec/tree/v1.0.0/item-spec)\n(if it has spatial and temporal references included) or a valid\n[STAC Collection](https://github.com/radiantearth/stac-spec/tree/v1.0.0/collection-spec)\n(supported since openEO API version 1.1.0).\nThe assets to download are in both cases available in the property `assets`\nand have the same structure. All additional metadata is not strictly required\nto download the files, but are helpful for users to understand the data.\n\nSTAC Collections can either (1) add all assets as collection-level assets or\n(2) link to STAC Catalogs and STAC Items with signed URLs, which will provide a full\nSTAC catalog structure a client has to go through. Option 2 is overall the better \narchitectural choice and allows a fine-grained description of the processed data,\nbut it is not compliant with previous versions of the openEO API.\n**To maintain backward compatibility, it is REQUIRED to still copy\nall assets in the STAC catalog structure into the collection-level assets.**\nThis requirement is planned to be removed in openEO API version 2.0.0.\nA client can enforce that the server returns a GeoJSON through content negotiation\nwith the media type `application/geo+json`, but the results may not contain very\nmeaningful metadata aside from the assets.\n\nClients are RECOMMENDED to store this response and all potential sub-catalogs\nand items with the assets so that the downloaded data is then a self-contained\nSTAC catalog user could publish easily with all the data and metadata.\n\nURL signing is a way to protect files from unauthorized access with a\nkey in the URL instead of HTTP header based authorization. The URL\nsigning key is similar to a password and its inclusion in the URL allows\nto download files using simple GET requests supported by a wide range of\nprograms, e.g. web browsers or download managers. Back-ends are\nresponsible to generate the URL signing keys and to manage their\nappropriate expiration. The back-end MAY indicate an expiration time by\nsetting the `expires` property in the reponse. Requesting this endpoint\nSHOULD always return non-expired URLs. Signed URLs that were generated\nfor a previous request and already expired SHOULD NOT be reused,\nbut regenerated with new expiration time.\nSigned URLs that expired MAY return the openEO error `ResultLinkExpired`.\n\nIt is **strongly recommended** to add a link with relation type `canonical`\nto the STAC Item or STAC Collection (see the `links` property for details).\n\nIf processing has not finished yet and the `partial` parameter is not set to `true`\nrequests to this endpoint MUST be rejected with openEO error `JobNotFinished`.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "name": "partial", + "description": "If set to `true`, the results endpoint returns incomplete results while still running.\nEnabling this parameter requires to indicate the status of the batch job in the STAC metadata by setting the `openeo:status`.", + "in": "query", + "allowEmptyValue": true, + "schema": { + "type": "boolean", + "default": false + } + } + ], + "responses": { + "200": { + "description": "Valid download links have been returned. The download links doesn't necessarily need to be located under the API base url.", + "headers": { + "OpenEO-Costs": { + "description": "Specifies the costs for fully downloading the data **once**, i.e. this header MAY change in subsequent calls. It MUST be set to `0` if the requester is the owner of the job and still has free downloads included in his processing charges estimated by `GET /jobs/{job_id}/estimate`. If a requester other than the owner is requesting the data of a shared job this header indicates the costs for the requester.", + "schema": { + "$ref": "#/components/schemas/money" + } + } + }, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/batch_job_result" + }, + { + "title": "Batch Job Results Response as STAC Collection", + "type": "object", + "required": [ + "assets" + ], + "properties": { + "openeo:status": { + "$ref": "#/components/schemas/result_status" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/collection" + } + ], + "example": { + "stac_version": "1.0.0", + "id": "a3cca2b2aa1e3b5b", + "title": "NDVI based on Sentinel 2", + "description": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2", + "license": "Apache-2.0", + "providers": [ + { + "name": "Example Cloud Corp.", + "description": "No further processing applied.", + "roles": [ + "producer", + "licensor", + "host" + ], + "url": "https://cloud.example" + } + ], + "extent": { + "temporal": { + "interval": [ + [ + "2019-08-24T14:15:22Z", + "2019-08-24T14:15:22Z" + ] + ] + }, + "spatial": { + "bbox": [ + [ + -180, + -90, + 180, + 90 + ] + ] + } + }, + "assets": { + "preview.png": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/preview.png", + "type": "image/png", + "title": "Thumbnail", + "roles": [ + "thumbnail" + ] + }, + "process.json": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/process.json", + "type": "application/json", + "title": "Original Process", + "roles": [ + "process", + "reproduction" + ] + }, + "1.tif": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/1.tif", + "type": "image/tiff; application=geotiff", + "roles": [ + "data" + ] + }, + "2.tif": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/2.tif", + "type": "image/tiff; application=geotiff", + "roles": [ + "data" + ] + }, + "inspire.xml": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/inspire.xml", + "type": "application/xml", + "title": "INSPIRE metadata", + "description": "INSPIRE compliant XML metadata", + "roles": [ + "metadata" + ] + } + }, + "links": [ + { + "rel": "canonical", + "type": "application/json", + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/collection.json" + }, + { + "rel": "item", + "type": "application/geo+json", + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item_1.json" + }, + { + "rel": "item", + "type": "application/geo+json", + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item_2.json" + } + ] + } + } + ] + } + }, + "application/geo+json": { + "schema": { + "$ref": "#/components/schemas/batch_job_result" + } + } + } + }, + "424": { + "description": "The request can't be fulfilled as the batch job failed. This request will deliver the last error message that was produced by the batch job.\n\nThis HTTP code MUST be sent only when the job `status` is `error`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/log_entry" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "post": { + "summary": "Start processing a batch job", + "operationId": "start-job", + "description": "Adds a batch job to the processing queue to compute the results.\n\nThe result will be stored in the format specified in the process.\nTo specify the format use a process such as `save_result`.\n\nThe job status is set to `queued`, if processing doesn't start\ninstantly. The same applies if the job status is `canceled`, `finished`,\nor `error`, which restarts the job and discards previous results if the\nback-end doesn't reject the request with an error.\nClients SHOULD warn users and ask for confirmation if results may get\ndiscarded.\n\n* Once the processing starts the status is set to `running`.\n* Once the data is available to download the status is set to\n`finished`.\n* Whenever an error occurs during processing, the status MUST be set to\n`error`.\n\nThis endpoint has no effect if the job status is already `queued` or\n`running`. In particular, it doesn't restart a running job. To restart\na queued or running job, processing MUST have been canceled before.\n\nBack-ends SHOULD reject queueing jobs with openEO error `PaymentRequired`,\nif the back-end is able to detect that the budget is too low to fully\nprocess the request. Alternatively, back-ends MAY provide partial results\nonce reaching the budget. If none of the alternatives is feasible, the\nresults are discarded. Thus, client SHOULD warn users that reaching the\nbudget may lead to partial or no results at all.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "202": { + "description": "The creation of the resource has been queued successfully." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "delete": { + "summary": "Cancel processing a batch job", + "operationId": "stop-job", + "description": "Cancels all related computations for this job at the back-end. It will\nstop generating additional costs for processing.\n\nA subset of processed results may be available for downloading depending\non the state of the job at the time it was canceled.\n\nResults MUST NOT be deleted until the job processing is started again or\nthe job is completely deleted through a request to\n`DELETE /jobs/{job_id}`.\n\nThis endpoint only has an effect if the job status is `queued` or\n`running`.\n\nThe job status is set to `canceled` if the status was `running`\nbeforehand and partial or preliminary results are available to be\ndownloaded. Otherwise the status is set to `created`. ", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "Processing the job has been successfully canceled." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/files": { + "get": { + "summary": "List all files in the workspace", + "operationId": "list-files", + "description": "Lists all user-uploaded files that are stored at the back-end.", + "tags": [ + "File Storage" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Flattened file tree with path relative to the user's root directory and some basic properties such as the file size and the timestamp of the last modification. All properties except the name are optional. Folders MUST NOT be listed separately so each element in the list MUST be a downloadable file.", + "content": { + "application/json": { + "schema": { + "title": "Workspace Files", + "type": "object", + "required": [ + "files", + "links" + ], + "properties": { + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/file" + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + }, + "example": { + "files": [ + { + "path": "test.txt", + "size": 182, + "modified": "2015-10-20T17:22:10Z" + }, + { + "path": "test.tif", + "size": 183142, + "modified": "2017-01-01T09:36:18Z" + }, + { + "path": "Sentinel2/S2A_MSIL1C_20170819T082011_N0205_R121_T34KGD_20170819T084427.zip", + "size": 4183353142, + "modified": "2018-01-03T10:55:29Z" + } + ], + "links": [] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/files/{path}": { + "parameters": [ + { + "name": "path", + "in": "path", + "description": "Path of the file, relative to the user's root directory. MAY include folders, but MUST not include relative references such as `.` and `..`.\n\nFolder and file names in the path MUST be url-encoded. The path separator `/` and the file extension separator `.` MUST NOT be url-encoded.\n\nThe URL-encoding may be shown incorrectly in rendered versions due to [OpenAPI 3 not supporting path parameters which contain slashes](https://github.com/OAI/OpenAPI-Specification/issues/892). This may also lead to OpenAPI validators not validating paths containing folders correctly.", + "required": true, + "schema": { + "type": "string" + }, + "examples": { + "normal": { + "description": "A path without special chars. It describes a file `europe.geojson` in a folder called `borders`.", + "value": "borders/europe.geojson" + }, + "specialchars": { + "description": "A path with special chars. It describes a file `m\u00fcnster.shp` in folders called `europe` and `\u00f6sterreich`.", + "value": "europe/%C3%B6sterreich/m%C3%BCnster.shp" + } + } + } + ], + "get": { + "summary": "Download a file from the workspace", + "operationId": "download-file", + "description": "Offers a file from the user workspace for download. The file is identified by its path relative to the user's root directory.\nIf a folder is specified as path a `FileOperationUnsupported` error MUST be sent as response.", + "tags": [ + "File Storage" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "A file from the workspace.", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "put": { + "summary": "Upload a file to the workspace", + "operationId": "upload-file", + "description": "Uploads a new file to the given path or updates an existing file if a file at the path exists.\n\nFolders are created once required by a file upload. Empty folders can't be created.", + "tags": [ + "File Storage" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "The file has been uploaded successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/file" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + }, + "delete": { + "summary": "Delete a file from the workspace", + "operationId": "delete-file", + "description": "Deletes an existing user-uploaded file specified by its path. Resulting empty folders MUST be deleted automatically.\n\nBack-ends MAY support deleting folders including its files and sub-folders. If not supported by the back-end a `FileOperationUnsupported` error MUST be sent as response.", + "tags": [ + "File Storage" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "The file has been successfully deleted at the back-end." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/me": { + "get": { + "summary": "Information about the authenticated user", + "operationId": "describe-account", + "description": "Lists information about the authenticated user, e.g. the user id.\nThe endpoint MAY return the disk quota available to the user. The endpoint MAY also return links related to user management and the user profile, e.g. where payments are handled or the user profile could be edited.\nFor back-ends that involve accounting, this service MAY also return the currently available money or credits in the currency the back-end is working with.\nThis endpoint MAY be extended to fulfil the specification of the [OpenID Connect UserInfo Endpoint](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo).", + "tags": [ + "Account Management" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Information about the logged in user.", + "content": { + "application/json": { + "schema": { + "title": "User Data", + "description": "Holds user information. If no budget or storage limit applies to the user account the corresponding properties MUST be set to null.", + "type": "object", + "required": [ + "user_id" + ], + "properties": { + "user_id": { + "type": "string", + "description": "A unique user identifier specific to the back-end, which could either be chosen by a user or is automatically generated by the back-end during the registration process at the back-end.\nIt is meant to be used as an identifier in URIs (e.g. for sharing purposes), which is primarily used in machine-to-machine communication. Preferrably use the human-readable property `name` to display the user's name in user interfaces instead of the user identifier.", + "pattern": "^[\\w\\-\\.~]+$", + "example": "john_doe" + }, + "name": { + "type": "string", + "description": "The user name, a human-friendly displayable name. Could be the user's real name or a nickname." + }, + "default_plan": { + "type": "string", + "description": "Name of the single plan the user is currently subscribed to if any.", + "example": "free" + }, + "storage": { + "title": "User Storage", + "description": "Information about the storage space available to the user.", + "type": "object", + "nullable": true, + "required": [ + "free", + "quota" + ], + "properties": { + "free": { + "type": "integer", + "description": "Free storage space in bytes, which is still available to the user. Effectively, this is the disk quota minus the used space by the user, e.g. user-uploaded files and job results.", + "example": 536870912 + }, + "quota": { + "type": "integer", + "description": "Maximum storage space (disk quota) in bytes available to the user.", + "example": 1073741824 + } + } + }, + "budget": { + "type": "number", + "nullable": true, + "description": "The remaining budget a user has available.\nThe value MUST be specified in the currency of the back-end.\nThe value SHOULD be set to `null` if no explicit limit applies." + }, + "links": { + "description": "Links related to the user profile, e.g. where payments\nare handled or the user profile could be edited.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `payment`: A page where users can recharge their user account with money or credits.\n\n2. `edit-form`: Points to a page where the user can edit his user profile.\n\n3. `alternate`: Any other representation of these (and potentially additional)\nuser information, e.g. the (public) user profile page.\nIt is RECOMMENDED to add descriptive titles for a better user experience.\n\n4. `related`: Any other user-specific links to be shown in clients,\ne.g. to user-specific settings, invoices, etc. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "href": "https://openeo.example/john_doe/payment/", + "rel": "payment" + }, + { + "href": "https://openeo.example/john_doe/edit/", + "rel": "edit-form" + }, + { + "href": "https://openeo.example/john_doe/", + "rel": "alternate", + "type": "text/html", + "title": "User profile" + }, + { + "href": "https://openeo.example/john_doe.vcf", + "rel": "alternate", + "type": "text/vcard", + "title": "vCard of John Doe" + }, + { + "href": "https://openeo.example/john_doe/invoices", + "rel": "related", + "type": "text/html", + "title": "Invoices" + } + ] + } + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + } + }, + "components": { + "schemas": { + "conformsTo": { + "description": "Lists all conformance classes specified in various standards that the\nimplementation conforms to. Conformance classes are commonly used in\nall OGC APIs and the STAC API specification.\n\nThe general openEO conformance class is `https://api.openeo.org/1.2.0`.\nSee the individual openEO API extensions for their conformance classes.\n\nThis property is REQUIRED for STAC API versions 1.0.0-beta.1 and later.", + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "example": [ + "https://api.openeo.org/1.2.0", + "https://api.openeo.org/extensions/commercial-data/0.1.0", + "https://api.openeo.org/extensions/federation/0.1.0", + "https://api.stacspec.org/v1.0.0/collections" + ] + }, + "udf_runtime": { + "type": "object", + "required": [ + "type", + "default" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/object_title" + }, + "description": { + "$ref": "#/components/schemas/description" + }, + "type": { + "type": "string", + "description": "The type of the UDF runtime.\n\nPredefined types are:\n* `language` for Programming Languages and\n* `docker` for Docker Containers.\n\nThe types can potentially be extended by back-ends." + }, + "default": { + "type": "string" + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "links": { + "type": "array", + "description": "Links related to this runtime, e.g. external documentation.\n\nIt is highly RECOMMENDED to provide at least links with\nthe following `rel` (relation) types:\n\n1. `about`: A resource that further explains the runtime,\ne.g. a user guide or the documentation. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } + } + }, + "discriminator": { + "propertyName": "type", + "mapping": { + "language": "#/components/schemas/udf_programming_language", + "docker": "#/components/schemas/udf_docker" + } + } + }, + "udf_programming_language": { + "allOf": [ + { + "$ref": "#/components/schemas/udf_runtime" + }, + { + "title": "Programming language", + "required": [ + "versions" + ], + "properties": { + "default": { + "type": "string", + "description": "The default version. MUST be one of the keys in the `versions` object." + }, + "versions": { + "title": "Programming language versions", + "description": "Versions available for the programming language.", + "type": "object", + "additionalProperties": { + "x-additionalPropertiesName": "Programming Language Version", + "title": "Programming language version", + "type": "object", + "required": [ + "libraries" + ], + "properties": { + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "libraries": { + "description": "Map of installed libraries, modules, packages or extensions for the programming language. The names of them are used as the property keys.", + "additionalProperties": { + "x-additionalPropertiesName": "Library Name", + "title": "Programming language library", + "type": "object", + "required": [ + "version" + ], + "properties": { + "version": { + "type": "string", + "description": "Version number of the library." + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "links": { + "type": "array", + "description": "Additional links related to this library,\ne.g. external documentation for this library.\n\nIt is highly RECOMMENDED to provide links with\nthe following `rel` (relation) types:\n\n1. `about`: A resource that further explains the library,\ne.g. a user guide or the documentation. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\n2. `latest-version`: If a library has been marked as deprecated,\na link SHOULD point to either a new library replacing the deprecated\nlibrary or a latest version of the library available at the back-end.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } + } + } + } + } + } + } + } + } + } + ] + }, + "udf_docker": { + "allOf": [ + { + "$ref": "#/components/schemas/udf_runtime" + }, + { + "title": "Docker container", + "required": [ + "docker", + "tags" + ], + "properties": { + "docker": { + "type": "string", + "description": "Identifier of a Docker image on Docker Hub or a private repository, which can run openEO UDFs. This is what is used in the `docker pull` command excluding the tag, e.g. `php`, `mcr.microsoft.com/dotnet/runtime` or `myregistry.local:5000/testing/test-image`." + }, + "default": { + "type": "string", + "description": "The default tag. MUST be one of the values in the `tags` array." + }, + "tags": { + "type": "array", + "description": "The docker tags that are supported.", + "minItems": 1, + "items": { + "type": "string" + } + } + } + } + ] + }, + "result_status": { + "type": "string", + "enum": [ + "running", + "canceled", + "finished", + "error" + ], + "description": "The status of a batch job.\n\nThis field is REQUIRED if the `partial` parameter is given.\nThis field is strongly RECOMMENDED if the job has stopped due to an error.", + "default": "finished" + }, + "batch_job_result": { + "title": "Batch Job Results Response as STAC Item", + "description": "The STAC specification should be the main guidance for implementing this.\nSpecifying the `bbox` is strongly RECOMMENDED for STAC compliance, but can be omitted if the result is unlocated and the `geometry` is set to `null`.", + "type": "object", + "required": [ + "stac_version", + "id", + "type", + "geometry", + "properties", + "assets", + "links" + ], + "properties": { + "stac_version": { + "$ref": "#/components/schemas/stac_version" + }, + "stac_extensions": { + "$ref": "#/components/schemas/stac_extensions" + }, + "id": { + "$ref": "#/components/schemas/job_id" + }, + "type": { + "type": "string", + "description": "The GeoJSON type that applies to this metadata document, which MUST always be a \"Feature\" according to the STAC specification.\nThis type does **not** describe the spatial data type of the assets.", + "enum": [ + "Feature" + ] + }, + "bbox": { + "$ref": "#/components/schemas/bbox" + }, + "geometry": { + "description": "Defines the full footprint of the asset represented by this item as\nGeoJSON Geometry.\n\nResults without a known location can set this value to `null`.", + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + } + ], + "example": { + "type": "Polygon", + "coordinates": [ + [ + [ + -180, + -90 + ], + [ + 180, + -90 + ], + [ + 180, + 90 + ], + [ + -180, + 90 + ], + [ + -180, + -90 + ] + ] + ] + } + }, + "properties": { + "type": "object", + "title": "Item Properties", + "description": "MAY contain additional properties other than the required property `datetime`, e.g. custom properties or properties from the STAC specification or STAC extensions.", + "required": [ + "datetime" + ], + "additionalProperties": true, + "properties": { + "datetime": { + "title": "Date and Time", + "description": "The searchable date/time of the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.\n\nIf this field is set to `null` (usually for larger time ranges), it is STRONGLY RECOMMENDED to specify both `start_datetime` and `end_datetime` for STAC compliance.", + "type": "string", + "format": "date-time", + "nullable": true + }, + "start_datetime": { + "type": "string", + "format": "date-time", + "description": "For time series: The first or start date and time for the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." + }, + "end_datetime": { + "type": "string", + "format": "date-time", + "description": "For time series: The last or end date and time for the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." + }, + "title": { + "$ref": "#/components/schemas/eo_title" + }, + "description": { + "$ref": "#/components/schemas/eo_description" + }, + "license": { + "$ref": "#/components/schemas/stac_license" + }, + "providers": { + "$ref": "#/components/schemas/stac_providers" + }, + "created": { + "$ref": "#/components/schemas/created" + }, + "updated": { + "$ref": "#/components/schemas/updated" + }, + "expires": { + "type": "string", + "format": "date-time", + "description": "Time until which the assets are accessible, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2020-11-01T00:00:00Z" + }, + "openeo:status": { + "$ref": "#/components/schemas/result_status" + } + } + }, + "assets": { + "$ref": "#/components/schemas/stac_assets" + }, + "links": { + "type": "array", + "description": "Links related to this batch job result, e.g. a link to an \ninvoice, additional log files or external documentation.\n\nThe links MUST NOT contain links to the processed and\ndownloadable data. Instead specify these in the `assets` property.\nClients MUST NOT download the data referenced in the links by\ndefault.\n\nIt is **strongly recommended** to add a link with relation type\n`canonical`, which points to this STAC document using a signed URL.\nThis way the STAC metadata can be used by non-openEO clients\nwithout additional authentication steps.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "rel": "canonical", + "type": "application/geo+json", + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item.json" + } + ] + } + } + }, + "file_format": { + "x-additionalPropertiesName": "File Format Name", + "title": "File Format", + "type": "object", + "description": "Describes a specific file format.", + "required": [ + "gis_data_types", + "parameters" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/object_title" + }, + "description": { + "$ref": "#/components/schemas/description" + }, + "gis_data_types": { + "type": "array", + "description": "Specifies the supported GIS spatial data types for this format.\nIt is RECOMMENDED to specify at least one of the data types, which will likely become a requirement in a future API version.", + "items": { + "type": "string", + "enum": [ + "raster", + "vector", + "table", + "pointcloud", + "other" + ] + } + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "parameters": { + "title": "File Format Parameters", + "description": "Specifies the supported parameters for this file format.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/resource_parameter" + } + }, + "links": { + "type": "array", + "description": "Links related to this file format, e.g. external documentation.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } + } + } + }, + "production": { + "type": "boolean", + "description": "Specifies whether the implementation is ready to be used in production use (`true`) or not (`false`).\nClients SHOULD only connect to non-production implementations if the user explicitly confirmed to use a non-production implementation.\nThis flag is part of `GET /.well-known/openeo` and `GET /`. It MUST be used consistently in both endpoints.", + "default": false + }, + "links_pagination": { + "description": "Links related to this list of resources, for example links for pagination\nor alternative formats such as a human-readable HTML version.\nThe links array MUST NOT be paginated.\n\nIf pagination is implemented, the following `rel` (relation) types apply:\n\n1. `next` (REQUIRED): A link to the next page, except on the last page.\n\n2. `prev` (OPTIONAL): A link to the previous page, except on the first page.\n\n3. `first` (OPTIONAL): A link to the first page, except on the first page.\n\n4. `last` (OPTIONAL): A link to the last page, except on the last page.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + } + }, + "link": { + "title": "Link", + "description": "A link to another resource on the web. Bases on [RFC 5899](https://www.rfc-editor.org/rfc/rfc5988.html).", + "type": "object", + "required": [ + "href", + "rel" + ], + "properties": { + "rel": { + "type": "string", + "description": "Relationship between the current document and the linked document. SHOULD be a [registered link relation type](https://www.iana.org/assignments/link-relations/link-relations.xml) whenever feasible.", + "example": "related" + }, + "href": { + "type": "string", + "description": "The value MUST be a valid URL.", + "format": "uri", + "example": "https://openeo.example" + }, + "type": { + "type": "string", + "description": "The value MUST be a string that hints at the format used to represent data at the provided URI, preferably a media (MIME) type.", + "example": "text/html" + }, + "title": { + "type": "string", + "description": "Used as a human-readable label for a link.", + "example": "openEO" + } + } + }, + "asset": { + "title": "STAC Asset", + "type": "object", + "required": [ + "href" + ], + "properties": { + "href": { + "title": "Asset location", + "description": "URL to the downloadable asset.\nThe URLs SHOULD be available without authentication so that external clients can download them easily. If the data is confidential, signed URLs SHOULD be used to protect against unauthorized access from third parties.", + "type": "string" + }, + "title": { + "description": "The displayed title for clients and users.", + "type": "string" + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "Multi-line description to explain the asset.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich\ntext representation." + }, + "type": { + "title": "Media Type", + "description": "Media type of the asset.", + "type": "string", + "example": "image/tiff; application=geotiff" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Purposes of the asset. Can be any value, but commonly used values are:\n\n* `thumbnail`: A visualization of the data, usually a lower-resolution true color image in JPEG or PNG format.\n* `reproducibility`: Information how the data was produced and/or can be reproduced, e.g. the process graph used to compute the data in JSON format.\n* `data`: The computed data in the format specified by the user in the process graph (applicable in `GET /jobs/{job_id}/results` only).\n* `metadata`: Additional metadata available for the computed data.", + "example": [ + "data" + ] + } + } + }, + "money": { + "description": "An amount of money or credits. The value MUST be specified in the currency the back-end is working with. The currency can be retrieved by calling `GET /`. If no currency is set, this field MUST be `null`.", + "type": "number", + "minimum": 0, + "example": 12.98, + "nullable": true, + "default": null + }, + "budget": { + "type": "number", + "minimum": 0, + "nullable": true, + "description": "Maximum amount of costs the request is allowed to produce.\nThe value MUST be specified in the currency of the back-end.\nNo limits apply, if the value is `null` or the back-end has no currency\nset in `GET /`.", + "example": 100, + "default": null + }, + "budget_update": { + "type": "number", + "minimum": 0, + "nullable": true, + "description": "Maximum amount of costs the request is allowed to produce.\nThe value MUST be specified in the currency of the back-end.\nNo limits apply, if the value is `null`.", + "example": 100 + }, + "billing_plan": { + "type": "string", + "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be handled in a *case insensitive* manner.\n\nThe plans can be retrieved from `GET /`, but the value returned here may\nnot be in the list of plans any longer.", + "example": "free" + }, + "billing_plan_null": { + "type": "string", + "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be accepted in a *case insensitive* manner.\nBack-ends MUST resolve the billing plan in the following way if billing is supported:\n\n* If a value is given and it is not `null`: Persist the `plan` that has been provided in the request.\n* Otherwise, don't change the billing plan.\n\nBilling plans not on the list of available plans MUST be rejected with\nopenEO error `BillingPlanInvalid`.", + "example": "free", + "nullable": true + }, + "billing_plan_null_default": { + "type": "string", + "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be accepted in a *case insensitive* manner.\nBack-ends MUST resolve the billing plan in the following way:\n\n* If a non-`null` value is given: Persist the `plan` that has been provided in the request.\n* Otherwise:\n 1. Persist the `default_plan` exposed through `GET /me`, if available.\n 2. Persist the `default_plan` exposed through `GET /`, if available.\n 3. If a single plan is exposed by the back-end, persist it.\n 4. Otherwise, the back-end MUST throw a `BillingPlanMissing` error.\n\nThe resolved plan MUST be persisted permanently, regardless of any \nchanges to the exposed billing plans in `GET /` in the future.\n\nBilling plans not on the list of available plans MUST be rejected with\nopenEO error `BillingPlanInvalid`.", + "example": "free", + "nullable": true, + "default": null + }, + "collection": { + "title": "Collection", + "type": "object", + "required": [ + "stac_version", + "id", + "description", + "license", + "extent", + "links" + ], + "properties": { + "stac_version": { + "$ref": "#/components/schemas/stac_version" + }, + "stac_extensions": { + "$ref": "#/components/schemas/stac_extensions" + }, + "type": { + "type": "string", + "enum": [ + "Collection" + ], + "description": "For STAC versions >= 1.0.0-rc.1 this field is required." + }, + "id": { + "$ref": "#/components/schemas/collection_id" + }, + "title": { + "type": "string", + "description": "A short descriptive one-line title for the collection." + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "Detailed multi-line description to explain the collection.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation." + }, + "keywords": { + "type": "array", + "description": "List of keywords describing the collection.", + "items": { + "type": "string" + } + }, + "version": { + "type": "string", + "description": "Version of the collection.\n\nThis property REQUIRES to add `version` (STAC < 1.0.0-rc.1) or\n`https://stac-extensions.github.io/version/v1.2.0/schema.json` (STAC >= 1.0.0-rc.1)\nto the list of `stac_extensions`." + }, + "deprecated": { + "type": "boolean", + "default": false, + "description": "Specifies that the collection is deprecated with the potential to\nbe removed. It should be transitioned out of usage as soon as\npossible and users should refrain from using it in new projects.\n\nA link with relation type `latest-version` SHOULD be added to the\nlinks and MUST refer to the collection that can be used instead.\n\nThis property REQUIRES to add `version` (STAC < 1.0.0-rc.1) or\n`https://stac-extensions.github.io/version/v1.2.0/schema.json` (STAC >= 1.0.0-rc.1)\nto the list of `stac_extensions`." + }, + "license": { + "$ref": "#/components/schemas/stac_license" + }, + "providers": { + "$ref": "#/components/schemas/stac_providers" + }, + "extent": { + "type": "object", + "title": "Collection Extent", + "description": "The extent of the data in the collection. Additional members MAY\nbe added to represent other extents, for example, thermal or\npressure ranges.\n\nThe first item in the array always describes the overall extent of\nthe data. All subsequent items describe more preciseextents,\ne.g. to identify clusters of data.\nClients only interested in the overall extent will only need to\naccess the first item in each array.", + "required": [ + "spatial", + "temporal" + ], + "properties": { + "spatial": { + "title": "Collection Spatial Extent", + "description": "The *potential* spatial extents of the features in the collection.", + "type": "object", + "properties": { + "bbox": { + "description": "One or more bounding boxes that describe the spatial extent\nof the dataset.\n\nThe first bounding box describes the overall spatial extent\nof the data. All subsequent bounding boxes describe more\nprecise bounding boxes, e.g. to identify clusters of data.\nClients only interested in the overall spatial extent will\nonly need to access the first item in each array.", + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/bbox" + } + } + } + }, + "temporal": { + "title": "Collection Temporal Extent", + "description": "The *potential* temporal extents of the features in the collection.", + "type": "object", + "properties": { + "interval": { + "description": "One or more time intervals that describe the temporal extent\nof the dataset.\n\nThe first time interval describes the overall temporal extent\nof the data. All subsequent time intervals describe more\nprecise time intervals, e.g. to identify clusters of data.\nClients only interested in the overall extent will only need\nto access the first item in each array.", + "type": "array", + "minItems": 1, + "items": { + "description": "Begin and end times of the time interval. The coordinate\nreference system is the Gregorian calendar.\n\nThe value `null` is supported and indicates an open time\ninterval.", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "example": [ + "2011-11-11T12:22:11Z", + null + ] + } + } + } + } + } + }, + "links": { + "description": "Links related to this collection.\nCould reference to licensing information, other meta data formats with\nadditional information or a preview image.\n\nIt is RECOMMENDED to provide links with the following\n`rel` (relation) types:\n\n1. `root` and `parent`: URL to the data discovery endpoint at `/collections`.\n\n2. `license`: A link to the license(s) SHOULD be specified if the `license`\nfield is set to `proprietary` or `various`.\n\n3. `example`: Links to examples of processes that use this collection.\n\n4. `latest-version`: If a collection has been marked as deprecated, a link SHOULD\npoint to the latest version of the collection. The relation types `predecessor-version`\n(link to older version) and `successor-version` (link to newer version) can also be used\nto show the relation between versions.\n\n5. `alternate`: An alternative representation of the collection.\nFor example, this could be the collection available through another\ncatalog service such as OGC CSW, a human-readable HTML version or a\nmetadata document following another standard such as ISO 19115 or DCAT.\n\n6. `http://www.opengis.net/def/rel/ogc/1.0/queryables`: URL to the\nqueryables endpoint at `/collections/{collection_id}/queryables`.\nFor JSON Schema documents, the `type` field must be set to `application/schema+json`.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking)\nand the STAC specification for Collections.", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + } + }, + "cube:dimensions": { + "title": "STAC Collection Cube Dimensions", + "description": "The named default dimensions of the data cube.\nNames must be unique per collection.\n\nThe keys of the object are the dimension names. For\ninteroperability, it is RECOMMENDED to use the\nfollowing dimension names if there is only a single\ndimension with the specified criteria:\n\n* `x` for the dimension of type `spatial` with the axis set to `x`\n* `y` for the dimension of type `spatial` with the axis set to `y`\n* `z` for the dimension of type `spatial` with the axis set to `z`\n* `t` for the dimension of type `temporal`\n* `bands` for dimensions of type `bands`\n* `geometry` for dimensions of type `geometry`\n\nThis property REQUIRES to add a version of the data cube extension to the list\nof `stac_extensions`, e.g. `https://stac-extensions.github.io/datacube/v2.2.0/schema.json`.", + "type": "object", + "additionalProperties": { + "x-additionalPropertiesName": "Dimension Name", + "allOf": [ + { + "$ref": "#/components/schemas/dimension" + } + ] + } + }, + "summaries": { + "title": "STAC Summaries (Collection Properties)", + "description": "Collection properties from STAC extensions (e.g. EO,\nSAR, Satellite or Scientific) or even custom extensions.\n\nSummaries are either a unique set of all available\nvalues, statistics *or* a JSON Schema. Statistics only\nspecify the range (minimum and maximum values) by default,\nbut can optionally be accompanied by additional\nstatistical values. The range can specify the\npotential range of values, but it is recommended to be\nas precise as possible. The set of values MUST contain\nat least one element and it is strongly RECOMMENDED to\nlist all values. It is recommended to list as many\nproperties as reasonable so that consumers get a full\noverview of the Collection. Properties that are\ncovered by the Collection specification (e.g.\n`providers` and `license`) SHOULD NOT be repeated in the\nsummaries.\n\nPotential fields for the summaries can be found here:\n\n* **[STAC Common Metadata](https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/common-metadata.md)**:\n A list of commonly used fields throughout all domains\n* **[Content Extensions](https://github.com/radiantearth/stac-spec/blob/v1.0.0/extensions/README.md#list-of-content-extensions)**:\n Domain-specific fields for domains such as EO, SAR and point clouds.\n* **Custom Properties**:\n It is generally allowed to add custom fields.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "array", + "title": "Set of values", + "items": { + "description": "A value of any type." + } + }, + { + "$ref": "#/components/schemas/collection_summary_stats" + }, + { + "$ref": "#/components/schemas/json_schema" + } + ] + } + }, + "assets": { + "description": "Dictionary of asset objects for data that can be downloaded,\neach with a unique key.\nThe keys MAY be used by clients as file names.\n\nImplementing this property REQUIRES to add `collection-assets`\nto the list of `stac_extensions` in STAC < 1.0.0-rc.1.", + "allOf": [ + { + "$ref": "#/components/schemas/stac_assets" + } + ] + } + } + }, + "stac_version": { + "type": "string", + "description": "The [version of the STAC specification](https://github.com/radiantearth/stac-spec/releases), which MAY not be equal to the [STAC API version](#tag/EO-Data-Discovery/STAC). Supports versions 0.9.x and 1.x.x.", + "pattern": "^(0\\.9.\\d+|1\\.\\d+.\\d+)", + "example": "1.0.0" + }, + "stac_extensions": { + "type": "array", + "description": "A list of implemented STAC extensions. The list contains URLs to the JSON Schema files it can be validated against. For STAC < 1.0.0-rc.1 shortcuts such as `sar` can be used instead of the schema URL.", + "uniqueItems": true, + "items": { + "anyOf": [ + { + "title": "Reference to a JSON Schema", + "type": "string", + "format": "uri", + "example": "https://openeo.example/stac/custom-extemsion/v1.0.0/schema.json" + }, + { + "title": "Reference to a core extension (STAC < 1.0.0-rc.1 only)", + "type": "string", + "example": "datacube" + } + ] + } + }, + "stac_license": { + "type": "string", + "description": "License(s) of the data as a SPDX [License identifier](https://spdx.org/licenses/).\nAlternatively, use `proprietary` if the license is not on the SPDX\nlicense list or `various` if multiple licenses apply. In these two cases\nlinks to the license texts SHOULD be added, see the `license` link\nrelation type.\n\nNon-SPDX licenses SHOULD add a link to the license text with the\n`license` relation in the links section. The license text MUST NOT be\nprovided as a value of this field. If there is no public license URL\navailable, it is RECOMMENDED to host the license text and link to it.", + "example": "Apache-2.0" + }, + "stac_providers": { + "type": "array", + "description": "A list of providers, which MAY include all organizations capturing or processing the data or the hosting provider. Providers SHOULD be listed in chronological order with the most recent provider being the last element of the list.", + "items": { + "type": "object", + "title": "Provider", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "The name of the organization or the individual.", + "type": "string", + "example": "Example Cloud Corp." + }, + "description": { + "description": "Multi-line description to add further provider information such as processing details for processors and producers, hosting details for hosts or basic contact information.\n\nCommonMark 0.29 syntax MAY be used for rich text representation.", + "type": "string", + "example": "No further processing applied." + }, + "roles": { + "description": "Roles of the provider.\n\nThe provider's role(s) can be one or more of the following\nelements:\n* `licensor`: The organization that is licensing the dataset under\nthe license specified in the collection's license field.\n* `producer`: The producer of the data is the provider that\ninitially captured and processed the source data, e.g. ESA for\nSentinel-2 data.\n* `processor`: A processor is any provider who processed data to a\nderived product.\n* `host`: The host is the actual provider offering the data on their\nstorage. There SHOULD be no more than one host, specified as last\nelement of the list.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "producer", + "licensor", + "processor", + "host" + ] + }, + "example": [ + "producer", + "licensor", + "host" + ] + }, + "url": { + "description": "Homepage on which the provider describes the dataset and publishes contact information.", + "type": "string", + "format": "uri", + "example": "https://cloud.example" + } + } + } + }, + "stac_assets": { + "type": "object", + "title": "Assets", + "description": "Dictionary of asset objects for data that can be downloaded, each with a\nunique key. The keys MAY be used by clients as file names.", + "additionalProperties": { + "$ref": "#/components/schemas/asset" + }, + "example": { + "preview.png": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/preview.png", + "type": "image/png", + "title": "Thumbnail", + "roles": [ + "thumbnail" + ] + }, + "process.json": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/process.json", + "type": "application/json", + "title": "Original Process", + "roles": [ + "process", + "reproduction" + ] + }, + "1.tif": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/1.tif", + "type": "image/tiff; application=geotiff", + "title": "Band 1", + "roles": [ + "data" + ] + }, + "2.tif": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/2.tif", + "type": "image/tiff; application=geotiff", + "title": "Band 2", + "roles": [ + "data" + ] + }, + "inspire.xml": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/inspire.xml", + "type": "application/xml", + "title": "INSPIRE metadata", + "description": "INSPIRE compliant XML metadata", + "roles": [ + "metadata" + ] + } + } + }, + "collection_summary_stats": { + "type": "object", + "title": "Statistics / Range", + "description": "By default, only ranges with a minimum and a maximum value can be specified. Ranges can be specified for ordinal values only, which means they need to have a rank order. Therefore, ranges can only be specified for numbers and some special types of strings. Examples: grades (A to F), dates or times. Implementors are free to add other derived statistical values to the object, for example `mean` or `stddev`.", + "required": [ + "minimum", + "maximum" + ], + "properties": { + "minimum": { + "description": "The minimum value (inclusive).", + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + }, + "maximum": { + "description": "The maximum value (inclusive).", + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + }, + "bbox": { + "description": "Each bounding box is provided as four or six numbers,\ndepending on whether the coordinate reference system\nincludes a vertical axis (height or depth):\n\n* West (lower left corner, coordinate axis 1)\n* South (lower left corner, coordinate axis 2)\n* Base (optional, minimum value, coordinate axis 3)\n* East (upper right corner, coordinate axis 1)\n* North (upper right corner, coordinate axis 2)\n* Height (optional, maximum value, coordinate axis 3)\n\nThe coordinate reference system of the values is WGS 84\nlongitude/latitude (http://www.opengis.net/def/crs/OGC/1.3/CRS84).\n\nFor WGS 84 longitude/latitude the values are in most cases\nthe sequence of minimum longitude, minimum latitude, maximum\nlongitude and maximum latitude.\n\nHowever, in cases where the box spans the antimeridian the\nfirst value (west-most box edge) is larger than the third value\n(east-most box edge).\n\nIf the vertical axis is included, the third and the sixth\nnumber are the bottom and the top of the 3-dimensional bounding box.", + "type": "array", + "oneOf": [ + { + "title": "4 elements", + "minItems": 4, + "maxItems": 4 + }, + { + "title": "6 elements", + "minItems": 6, + "maxItems": 6 + } + ], + "items": { + "type": "number" + }, + "example": [ + -180, + -90, + 180, + 90 + ] + }, + "collection_id": { + "type": "string", + "description": "A unique identifier for the collection, which MUST match the specified pattern.", + "pattern": "^[\\w\\-\\.~\\/]+$", + "example": "Sentinel-2A" + }, + "dimension": { + "title": "Dimension", + "description": "A dimension, each object represents a distinct dimension with the key being the dimension name.", + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "description": "Type of the dimension.", + "type": "string", + "enum": [ + "spatial", + "temporal", + "bands", + "geometry", + "other" + ] + }, + "description": { + "$ref": "#/components/schemas/description" + } + }, + "discriminator": { + "propertyName": "type", + "mapping": { + "spatial": "#/components/schemas/dimension_spatial", + "temporal": "#/components/schemas/dimension_temporal", + "bands": "#/components/schemas/dimension_bands", + "geometry": "#/components/schemas/dimension_geometry", + "other": "#/components/schemas/dimension_other" + } + } + }, + "dimension_other": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" + }, + { + "title": "Additional Dimension", + "type": "object", + "properties": { + "extent": { + "$ref": "#/components/schemas/collection_dimension_extent_open" + }, + "values": { + "$ref": "#/components/schemas/collection_dimension_values" + }, + "step": { + "$ref": "#/components/schemas/collection_dimension_step" + }, + "unit": { + "$ref": "#/components/schemas/collection_dimension_unit" + }, + "reference_system": { + "description": "The reference system for the dimension.", + "type": "string" + } + } + } + ] + }, + "dimension_geometry": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" + }, + { + "title": "Geometry Dimension", + "type": "object", + "required": [ + "bbox" + ], + "properties": { + "axes": { + "description": "Axes of the vector dimension as an ordered set of `x`, `y` and `z`. Defaults to `x` and `y`.", + "default": [ + "x", + "y" + ], + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/dimension_axis_xyz" + } + }, + "bbox": { + "$ref": "#/components/schemas/bbox" + }, + "values": { + "description": "Optionally, a representation of the vectors. This can be a list of WKT string or other free-form identifiers.", + "type": "array", + "items": { + "type": "string" + } + }, + "geometry_types": { + "description": "A set of all geometry types included in this dimension. If not present, mixed geometry types must be assumed.", + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/geometry_type" + } + }, + "reference_system": { + "$ref": "#/components/schemas/collection_dimension_srs" + } + } + } + ] + }, + "dimension_bands": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" + }, + { + "title": "Band Dimension", + "description": "A dimension for the bands.\n\nThe band dimension only specifies the band names\nas dimension labels. Further information to the\nbands are available in either `sar:bands` or\n`eo:bands` in the `summaries` property.", + "type": "object", + "required": [ + "values" + ], + "properties": { + "values": { + "$ref": "#/components/schemas/collection_dimension_values" + } + } + } + ] + }, + "dimension_spatial": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" + }, + { + "title": "Spatial Dimension", + "description": "A spatial (raster) dimension in one of the horizontal (x or y) or vertical (z) directions.", + "type": "object", + "required": [ + "axis" + ], + "properties": { + "axis": { + "$ref": "#/components/schemas/dimension_axis_xyz" + }, + "extent": { + "description": "Extent (lower and upper bounds) of the dimension as two-dimensional array. Open intervals with `null` are not allowed.", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "number" + } + }, + "values": { + "description": "A set of all potential values.", + "type": "array", + "minItems": 1, + "items": { + "type": "number" + } + }, + "step": { + "$ref": "#/components/schemas/collection_dimension_step" + }, + "reference_system": { + "$ref": "#/components/schemas/collection_dimension_srs" + } + }, + "discriminator": { + "propertyName": "axis", + "mapping": { + "x": "#/components/schemas/dimension_spatial_horizontal", + "y": "#/components/schemas/dimension_spatial_horizontal", + "z": "#/components/schemas/dimension_spatial_vertical" + } + } + } + ] + }, + "dimension_axis_xyz": { + "title": "Axis", + "description": "Axis of a geometry or dimension (`x`, `y` or `z`)", + "type": "string", + "enum": [ + "x", + "y", + "z" + ] + }, + "dimension_spatial_horizontal": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension_spatial" + }, + { + "title": "Horizontal Spatial Dimension", + "required": [ + "extent" + ] + } + ] + }, + "dimension_spatial_vertical": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension_spatial" + }, + { + "title": "Vertical Spatial Dimension", + "anyOf": [ + { + "title": "Vertical Spatial Dimension with Extent", + "required": [ + "extent" + ] + }, + { + "title": "Vertical Spatial Dimension with Values", + "required": [ + "values" + ] + } + ] + } + ] + }, + "dimension_temporal": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" + }, + { + "title": "Temporal Dimension", + "description": "A temporal dimension based on the ISO 8601 standard. The temporal reference system for the data is expected to be ISO 8601 compliant (Gregorian calendar / UTC). Data not compliant with ISO 8601 can be represented as an *Additional Dimension Object* with `type` set to `temporal`.", + "type": "object", + "required": [ + "extent" + ], + "properties": { + "values": { + "description": "If the dimension consists of set of specific values they can be listed here. The dates and/or times MUST be strings compliant to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601).", + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "extent": { + "description": "Extent (lower and upper bounds) of the dimension as two-dimensional array. The dates and/or times MUST be strings compliant to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601). `null` is allowed for open date ranges.", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "string", + "nullable": true + } + }, + "step": { + "description": "The space between the temporal instances as [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations), e.g. `P1D`. Use `null` for irregularly spaced steps.", + "type": "string", + "nullable": true + } + } + } + ] + }, + "collection_dimension_srs": { + "title": "Spatial reference system", + "description": "The spatial reference system for the data, specified as [EPSG code](http://www.epsg-registry.org/), [WKT2 (ISO 19162) string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html), [PROJJSON object](https://proj.org/specifications/projjson.html) or [PROJ definition (deprecated)](https://proj.org/usage/quickstart.html). Defaults to EPSG code 4326.", + "default": 4326, + "oneOf": [ + { + "type": "number", + "title": "EPSG code" + }, + { + "type": "string", + "title": "WKT2 or PROJ definition (deprecated)" + }, + { + "type": "object", + "title": "PROJJSON" + } + ] + }, + "collection_dimension_extent_open": { + "description": "If the dimension consists of [ordinal](https://en.wikipedia.org/wiki/Level_of_measurement#Ordinal_scale) values, the extent (lower and upper bounds) of the values as two-dimensional array. Use `null` for open intervals.", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "number", + "nullable": true + } + }, + "collection_dimension_values": { + "description": "A set of all potential values, especially useful for [nominal](https://en.wikipedia.org/wiki/Level_of_measurement#Nominal_level) values.\n\n**Important:** The order of the values MUST be exactly how the dimension values are also ordered in the data (cube). If the values specify band names, the values MUST be in the same order as they are in the corresponding band fields (i.e. `eo:bands` or `sar:bands`).", + "type": "array", + "minItems": 1, + "items": { + "oneOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + } + }, + "collection_dimension_step": { + "description": "If the dimension consists of [interval](https://en.wikipedia.org/wiki/Level_of_measurement#Interval_scale) values, the space between the values. Use `null` for irregularly spaced steps.", + "type": "number", + "nullable": true + }, + "collection_dimension_unit": { + "description": "The unit of measurement for the data, preferably compliant to [UDUNITS-2](https://ncics.org/portfolio/other-resources/udunits2/) units (singular).", + "type": "string" + }, + "process_arguments": { + "title": "Process Arguments", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/process_argument_value" + } + }, + "process_argument_value": { + "title": "Process Argument Value", + "description": "Arguments for a process. See the API documentation for more information.", + "nullable": true, + "anyOf": [ + { + "type": "object", + "nullable": true, + "title": "Object (restricted)", + "properties": { + "from_parameter": { + "not": {} + }, + "from_node": { + "not": {} + }, + "process_graph": { + "not": {} + } + } + }, + { + "type": "string", + "title": "String" + }, + { + "type": "number", + "title": "Number (incl. integers)" + }, + { + "type": "boolean", + "title": "Boolean" + }, + { + "type": "array", + "title": "Array", + "items": { + "$ref": "#/components/schemas/process_argument_value" + } + }, + { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + { + "type": "object", + "title": "Result Reference", + "description": "Data that is expected to be passed from another process.", + "required": [ + "from_node" + ], + "properties": { + "from_node": { + "description": "The ID of the node that data is expected to come from.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "title": "Parameter Reference", + "description": "A parameter for a process graph. Data that is expected to be passed to a process graph either from the user directly or from the process that is executing the process graph.", + "required": [ + "from_parameter" + ], + "properties": { + "from_parameter": { + "description": "The name of the parameter that data is expected to come from.", + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "process_graph": { + "title": "Process Graph", + "description": "A process graph defines a graph-like structure as a connected set of executable processes. Each key is a unique identifier (node ID) that is used to refer to the process in the graph.", + "type": "object", + "additionalProperties": { + "x-additionalPropertiesName": "Node ID", + "title": "Process Node", + "type": "object", + "required": [ + "process_id", + "arguments" + ], + "properties": { + "process_id": { + "$ref": "#/components/schemas/process_id" + }, + "namespace": { + "$ref": "#/components/schemas/process_namespace" + }, + "result": { + "type": "boolean", + "description": "Used to specify which node is the last in the chain and returns the result to return to the requesting context. This flag MUST only be set once in each list of process nodes.", + "default": false + }, + "description": { + "description": "Optional description about the process and its arguments.", + "type": "string", + "nullable": true + }, + "arguments": { + "$ref": "#/components/schemas/process_arguments" + } + } + }, + "example": { + "dc": { + "process_id": "load_collection", + "arguments": { + "id": "Sentinel-2", + "spatial_extent": { + "west": 16.1, + "east": 16.6, + "north": 48.6, + "south": 47.2 + }, + "temporal_extent": [ + "2018-01-01", + "2018-02-01" + ] + } + }, + "bands": { + "process_id": "filter_bands", + "description": "Filter and order the bands. The order is important for the following reduce operation.", + "arguments": { + "data": { + "from_node": "dc" + }, + "bands": [ + "B08", + "B04", + "B02" + ] + } + }, + "evi": { + "process_id": "reduce", + "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", + "arguments": { + "data": { + "from_node": "bands" + }, + "dimension": "bands", + "reducer": { + "process_graph": { + "nir": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 0 + } + }, + "red": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 1 + } + }, + "blue": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 2 + } + }, + "sub": { + "process_id": "subtract", + "arguments": { + "data": [ + { + "from_node": "nir" + }, + { + "from_node": "red" + } + ] + } + }, + "p1": { + "process_id": "product", + "arguments": { + "data": [ + 6, + { + "from_node": "red" + } + ] + } + }, + "p2": { + "process_id": "product", + "arguments": { + "data": [ + -7.5, + { + "from_node": "blue" + } + ] + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_node": "nir" + }, + { + "from_node": "p1" + }, + { + "from_node": "p2" + } + ] + } + }, + "div": { + "process_id": "divide", + "arguments": { + "data": [ + { + "from_node": "sub" + }, + { + "from_node": "sum" + } + ] + } + }, + "p3": { + "process_id": "product", + "arguments": { + "data": [ + 2.5, + { + "from_node": "div" + } + ] + }, + "result": true + } + } + } + } + }, + "mintime": { + "process_id": "reduce", + "description": "Compute a minimum time composite by reducing the temporal dimension", + "arguments": { + "data": { + "from_node": "evi" + }, + "dimension": "temporal", + "reducer": { + "process_graph": { + "min": { + "process_id": "min", + "arguments": { + "data": { + "from_parameter": "data" + } + }, + "result": true + } + } + } + } + }, + "save": { + "process_id": "save_result", + "arguments": { + "data": { + "from_node": "mintime" + }, + "format": "GTiff" + }, + "result": true + } + } + }, + "process": { + "title": "Process", + "type": "object", + "properties": { + "id": { + "$ref": "#/components/schemas/process_id" + }, + "summary": { + "$ref": "#/components/schemas/process_summary" + }, + "description": { + "$ref": "#/components/schemas/process_description" + }, + "categories": { + "$ref": "#/components/schemas/process_categories" + }, + "parameters": { + "$ref": "#/components/schemas/process_parameters" + }, + "returns": { + "$ref": "#/components/schemas/process_return_value" + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "exceptions": { + "$ref": "#/components/schemas/process_exceptions" + }, + "examples": { + "type": "array", + "description": "Examples, may be used for unit tests.", + "items": { + "title": "Process Example", + "type": "object", + "required": [ + "arguments" + ], + "properties": { + "title": { + "type": "string", + "description": "A title for the example." + }, + "description": { + "$ref": "#/components/schemas/process_description" + }, + "arguments": { + "$ref": "#/components/schemas/process_arguments" + }, + "returns": { + "description": "The return value which can by of any data type." + } + } + } + }, + "links": { + "type": "array", + "description": "Links related to this process, e.g. additional external documentation.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `latest-version`: If a process has been marked as deprecated, a link SHOULD\npoint to the preferred version of the process. The relation types `predecessor-version`\n(link to older version) and `successor-version` (link to newer version) can also be used\nto show the relation between versions.\n\n2. `example`: Links to examples of other processes that use this process.\n\n3. `cite-as`: For all DOIs associated with the process, the respective DOI\nlinks SHOULD be added.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } + }, + "process_graph": { + "$ref": "#/components/schemas/process_graph" + } + } + }, + "user_defined_process_meta": { + "title": "User-defined Process Metadata", + "description": "A user-defined process, may only contain metadata and no process graph.", + "type": "object", + "required": [ + "id" + ], + "properties": { + "summary": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "parameters": { + "type": "array", + "nullable": true + }, + "returns": { + "type": "object", + "nullable": true + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/process" + } + ] + }, + "process_graph_with_metadata": { + "title": "Process Graph with metadata", + "description": "A process graph, optionally enriched with process metadata.", + "type": "object", + "required": [ + "process_graph" + ], + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "summary": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "parameters": { + "type": "array", + "nullable": true + }, + "returns": { + "type": "object", + "nullable": true + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/process" + } + ] + }, + "process_namespace": { + "type": "string", + "nullable": true, + "default": null, + "example": null, + "description": "The namespace the `process_id` is valid for.\n\nThe following options are predefined by the openEO API, but additional\nnamespaces may be introduced by back-ends or in a future version of the API.\n\n* `null` (default): Checks both user-defined and predefined processes,\n but prefers user-defined processes if both are available.\n This allows users to add missing predefined processes for portability,\n e.g. common processes from [processes.openeo.org](https://processes.openeo.org)\n that have a process graph included.\n It is RECOMMENDED to log the namespace selected by the back-end for debugging purposes.\n* `backend`: Uses exclusively the predefined processes listed at `GET /processes`.\n* `user`: Uses exclusively the user-defined processes listed at `GET /process_graphs`.\n\nIf multiple processes with the same identifier exist, Clients SHOULD\ninform the user that it's recommended to select a namespace." + }, + "process_id": { + "type": "string", + "description": "The identifier for the process. It MUST be unique across its namespace\n(e.g. predefined processes or user-defined processes).\n\nClients SHOULD warn the user if a user-defined process is added with the \nsame identifier as one of the predefined process.", + "pattern": "^\\w+$", + "example": "ndvi" + }, + "process_summary": { + "type": "string", + "description": "A short summary of what the process does." + }, + "process_categories": { + "type": "array", + "description": "A list of categories.", + "items": { + "type": "string", + "description": "Name of the category." + } + }, + "process_return_value": { + "type": "object", + "title": "Process Return Value", + "description": "Description of the data that is returned by this process.", + "required": [ + "schema" + ], + "properties": { + "description": { + "$ref": "#/components/schemas/process_description" + }, + "schema": { + "$ref": "#/components/schemas/process_schema" + } + } + }, + "experimental": { + "type": "boolean", + "description": "Declares that the specified entity is experimental, which means that it is likely to change or may produce unpredictable behaviour. Users should refrain from using it in production, but still feel encouraged to try it out and give feedback.", + "default": false + }, + "deprecated": { + "type": "boolean", + "description": "Declares that the specified entity is deprecated with the potential\nto be removed in any of the next versions. It should be transitioned out\nof usage as soon as possible and users should refrain from using it in\nnew implementations.", + "default": false + }, + "process_exceptions": { + "type": "object", + "title": "Process Exceptions", + "description": "Declares exceptions (errors) that might occur during execution\nof this process. This list is just for informative purposes and may be\nincomplete. This list MUST only contain exceptions that stop the\nexecution of a process and MUST NOT contain warnings, notices or\ndebugging messages. It is meant to primarily contain errors that\nhave been caused by the user. It is RECOMMENDED that exceptions\nare referred to and explained in process or parameter descriptions.\n\nThe keys define the error code and MUST match the following pattern:\n`^\\w+$`\n\nThis schema follows the schema of the general openEO error list (see\nerrors.json).", + "additionalProperties": { + "x-additionalPropertiesName": "Error Code", + "title": "Process Exception", + "type": "object", + "required": [ + "message" + ], + "properties": { + "description": { + "type": "string", + "format": "commonmark", + "description": "Detailed description to explain the error to client\nusers and back-end developers. This should not be shown in the\nclients directly, but MAY be linked to in the errors `url`\nproperty.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used\nfor rich text representation." + }, + "message": { + "type": "string", + "description": "Explains the reason the server is rejecting the request. This message is intended to be displayed to the client user. For \"4xx\" error codes the message SHOULD explain shortly how the client needs to modify the request.\n\nThe message MAY contain variables, which are enclosed by curly brackets. Example: `{variable_name}`", + "example": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}" + }, + "http": { + "type": "integer", + "description": "HTTP Status Code, following the [error handling conventions in openEO](#section/API-Principles/Error-Handling). Defaults to `400`.", + "default": 400 + } + } + } + }, + "process_parameters": { + "type": "array", + "description": "A list of parameters.\n\nThe order in the array corresponds to the parameter order to\nbe used in clients that don't support named parameters.\n\n**Note:** Specifying an empty array is different from (if allowed)\n`null` or the property being absent.\nAn empty array means the process has no parameters.\n`null` / property absent means that the parameters are unknown as\nthe user has not specified them. There could still be parameters in the\nprocess graph, if one is specified.", + "items": { + "$ref": "#/components/schemas/process_parameter" + } + }, + "base_parameter": { + "type": "object", + "required": [ + "name", + "description" + ], + "properties": { + "name": { + "type": "string", + "description": "A unique name for the parameter. \n\nIt is RECOMMENDED to use [snake case](https://en.wikipedia.org/wiki/Snake_case) (e.g. `window_size` or `scale_factor`).", + "pattern": "^\\w+$" + }, + "description": { + "$ref": "#/components/schemas/process_description" + }, + "optional": { + "type": "boolean", + "description": "Determines whether this parameter is optional to be specified even when no default is specified.\nClients SHOULD automatically set this parameter to `true`, if a default value is specified. Back-ends SHOULD NOT fail, if a default value is specified and this flag is missing.", + "default": false + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "default": { + "description": "The default value for this parameter. Required parameters SHOULD NOT specify a default value. Optional parameters SHOULD always specify a default value." + } + } + }, + "parameter": { + "title": "Parameter", + "type": "object", + "required": [ + "schema" + ], + "properties": { + "schema": { + "$ref": "#/components/schemas/data_type_schema" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/base_parameter" + } + ] + }, + "process_parameter": { + "title": "Process Parameter", + "type": "object", + "required": [ + "schema" + ], + "properties": { + "schema": { + "$ref": "#/components/schemas/process_schema" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/base_parameter" + } + ] + }, + "batch_job": { + "title": "Batch Job", + "description": "The metadata of a batch jobs that has been submitted by the authenticated user.", + "type": "object", + "required": [ + "id", + "status", + "created" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/job_id" + }, + "title": { + "$ref": "#/components/schemas/eo_title" + }, + "description": { + "$ref": "#/components/schemas/eo_description" + }, + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "status": { + "type": "string", + "enum": [ + "created", + "queued", + "running", + "canceled", + "finished", + "error" + ], + "description": "The current status of a batch job.\n\nThe following status changes can occur:\n* `POST /jobs`: The status is initialized as `created`.\n* `POST /jobs/{job_id}/results`: The status is set to `queued`, if\nprocessing doesn't start instantly.\n * Once the processing starts the status is set to `running`.\n * Once the data is available to download the status is set to `finished`.\n * Whenever an error occurs during processing, the status MUST be set to `error`.\n* `DELETE /jobs/{job_id}/results`: The status is set to `canceled` if\nthe status was `running` beforehand and partial or preliminary results\nare available to be downloaded. Otherwise the status is set to\n`created`. ", + "example": "running", + "default": "created" + }, + "progress": { + "type": "number", + "description": "Indicates the process of a running batch job in percent.\nCan also be set for a job which stopped due to an error or was canceled by the user. In this case, the value indicates the progress at which the job stopped. The Property may not be available for the status codes `created` and `queued`.\nSubmitted and queued jobs only allow the value `0`, finished jobs only allow the value `100`.", + "minimum": 0, + "maximum": 100, + "example": 75.5 + }, + "created": { + "$ref": "#/components/schemas/created" + }, + "updated": { + "$ref": "#/components/schemas/updated" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan" + }, + "costs": { + "$ref": "#/components/schemas/money" + }, + "budget": { + "$ref": "#/components/schemas/budget" + }, + "usage": { + "description": "Metrics about the resource usage of the batch job.\n\nBack-ends are not expected to update the metrics while processing data,\nso the metrics can only be available after the job has finished\nor has stopped due to an error.\nFor usage metrics during processing, metrics can better be added to the\nlogs (e.g. `GET /jobs/{job_id}/logs`) with the same schema.", + "allOf": [ + { + "$ref": "#/components/schemas/usage" + } + ] + }, + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" + }, + "links": { + "type": "array", + "description": "Links related to this batch job, e.g. a links to \ninvoices, log files or results.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `monitor`: If logs are available, a link to the [logs endpoint](#tag/Batch-Jobs/operation/debug-job).\n2. `result`: If batch job results are available, a link to the [results endpoint](#tag/Batch-Jobs/operation/list-results).\n\nThe relation types `monitor` and `result` may occur for various batch job states:\n\n1. `created`: When the batch job was executed before and has been reset to `created` after an\n [update](#tag/Batch-Jobs/operation/update-job) there could still be results and logs available\n until they get discarded by [queueing the batch job again](#tag/Batch-Jobs/operation/start-job).\n2. `finished`: The full log and results are expected to be available.\n3. `error` / `canceled`: Partial results and logs may be available.\n\nFor more relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "rel": "result", + "type": "application/json", + "title": "Batch Job Results", + "href": "https://openeo.example/api/v1/jobs/123/logs" + }, + { + "rel": "result", + "type": "application/json", + "title": "Batch Job Logs", + "href": "https://openeo.example/api/v1/jobs/123/logs" + } + ] + } + } + }, + "job_id": { + "type": "string", + "description": "Per-backend unique identifier of the batch job, generated by the back-end during creation. MUST match the specified pattern.", + "pattern": "^[\\w\\-\\.~]+$", + "example": "a3cca2b2aa1e3b5b" + }, + "created": { + "type": "string", + "format": "date-time", + "description": "Date and time of creation, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2017-01-01T09:32:12Z" + }, + "updated": { + "type": "string", + "format": "date-time", + "description": "Date and time of the last status change, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2017-01-01T09:36:18Z" + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "Detailed description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation." + }, + "object_title": { + "type": "string", + "description": "A human-readable short title to be displayed to users **in addition** to the names specified in the keys. This property is only for better user experience so that users can understand the names better. Example titles could be `GeoTiff` for the key `GTiff` (for file formats) or `OGC Web Map Service` for the key `WMS` (for service types). The title MUST NOT be used in communication (e.g. in process graphs), although clients MAY translate the titles into the corresponding names." + }, + "eo_title": { + "description": "A short description to easily distinguish entities.", + "type": "string", + "nullable": true, + "example": "NDVI based on Sentinel 2" + }, + "eo_description": { + "type": "string", + "format": "commonmark", + "description": "Detailed multi-line description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", + "nullable": true, + "example": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2" + }, + "process_description": { + "type": "string", + "format": "commonmark", + "description": "Detailed description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. In addition to the CommonMark syntax, clients can convert process IDs that are formatted as in the following example into links instead of code blocks: ``` ``process_id()`` ```" + }, + "service": { + "title": "Secondary Web Service", + "description": "The metadata of a secondary web service that has been submitted by the authenticated user.", + "type": "object", + "required": [ + "id", + "enabled", + "type", + "url" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/service_id" + }, + "title": { + "$ref": "#/components/schemas/eo_title" + }, + "description": { + "$ref": "#/components/schemas/eo_description" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL at which the secondary web service is accessible. Doesn't necessarily need to be located within the API.", + "example": "https://openeo.example/wms/wms-a3cca9" + }, + "type": { + "$ref": "#/components/schemas/service_type" + }, + "enabled": { + "$ref": "#/components/schemas/service_enabled" + }, + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "configuration": { + "$ref": "#/components/schemas/service_configuration" + }, + "attributes": { + "title": "Secondary Web Service Attributes", + "type": "object", + "description": "Additional attributes of the secondary web service, e.g. available layers for a WMS based on the bands in the underlying GeoTiff.", + "example": { + "layers": [ + "ndvi", + "evi" + ] + } + }, + "created": { + "$ref": "#/components/schemas/created" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan" + }, + "costs": { + "$ref": "#/components/schemas/money" + }, + "budget": { + "$ref": "#/components/schemas/budget" + }, + "usage": { + "description": "Metrics about the resource usage of the secondary web service.\n\nBack-ends are not expected to update the metrics in real-time.\nFor detailed usage metrics for individual processing steps, metrics\ncan be added to the logs (e.g. `GET /jobs/{job_id}/logs`) with the\nsame schema.", + "allOf": [ + { + "$ref": "#/components/schemas/usage" + } + ] + }, + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" + } + } + }, + "service_type": { + "description": "Definition of the service type to access result data. All available service types can be retrieved via `GET /service_types`. Service types MUST be accepted in a *case insensitive* manner.", + "type": "string", + "example": "wms" + }, + "service_configuration": { + "type": "object", + "title": "Service Configuration", + "description": "Map of configuration settings, i.e. the setting names supported by the secondary web service combined with actual values. See `GET /service_types` for supported configuration settings. For example, this could specify the required version of the service, visualization details or any other service dependant configuration.", + "example": { + "version": "1.3.0" + } + }, + "service_enabled": { + "type": "boolean", + "description": "Describes whether a secondary web service is responding to requests (true) or not (false). Disabled services don't produce any costs." + }, + "service_id": { + "type": "string", + "description": "A per-backend unique identifier of the secondary web service, generated by the back-end during creation. MUST match the specified pattern.", + "pattern": "^[\\w\\-\\.~]+$", + "example": "wms-a3cca9" + }, + "resource_parameter": { + "x-additionalPropertiesName": "Parameter Name", + "type": "object", + "title": "Resource Parameter", + "description": "Describes a parameter for various resources (e.g. file formats, service types).\n\nThe parameters are specified according to the [JSON Schema draft-07](http://json-schema.org/) specification.\nSee the chapter ['Schemas' in 'Defining Processes'](#section/Processes/Defining-Processes) for more information.\n\nThe following more complex JSON Schema keywords SHOULD NOT be used:\n`if`, `then`, `else`, `readOnly`, `writeOnly`, `dependencies`, `minProperties`, `maxProperties`, `patternProperties`.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved). This allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema is only a common subset of JSON Schema. Additional keywords MAY be used.", + "required": [ + "description" + ], + "properties": { + "description": { + "type": "string", + "description": "A brief description of the parameter according to [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.10.1)." + }, + "required": { + "type": "boolean", + "description": "Determines whether this parameter is mandatory.", + "default": false + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "default": { + "description": "The default value represents what would be assumed by the consumer of the input as the value of the parameter if none is provided. The value MUST conform to the defined type for the parameter defined at the same level. For example, if type is string, then default can be \"foo\" but cannot be 1. See [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.10.2)." + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/process_json_schema" + } + ] + }, + "error": { + "title": "General Error", + "description": "An error object declares additional information about a client-side or server-side error.\nSee also: * [Error Handling](#section/API-Principles/Error-Handling) in the API in general. * [Common Error Codes](errors.json)", + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "id": { + "type": "string", + "description": "A back-end MAY add a unique identifier to the error response to be able to log and track errors with further non-disclosable details. A client could communicate this id to a back-end provider to get further information.", + "example": "550e8400-e29b-11d4-a716-446655440000" + }, + "code": { + "$ref": "#/components/schemas/log_code" + }, + "message": { + "type": "string", + "description": "A message explaining what the client may need to change or what difficulties the server is facing.", + "example": "Parameter 'sample' is missing." + }, + "links": { + "$ref": "#/components/schemas/log_links" + } + } + }, + "log_code": { + "type": "string", + "description": "The code is either one of the standardized error codes or a custom code, for example specified by a user in the `inspect` process.", + "example": "SampleError" + }, + "log_links": { + "description": "Links related to this log entry / error, e.g. to a resource that\nprovides further explanations.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "href": "https://openeo.example/docs/errors/SampleError", + "rel": "about" + } + ] + }, + "log_level": { + "description": "The severity level of the log entry.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\n\nThe level `error` usually corresponds with critical issues that usually terminate the data processing.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "example": "error" + }, + "min_log_level_default": { + "description": "The minimum severity level for log entries that the back-end stores for the processing request.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the back-end will only store log entries with the level `warning` and `error`.\n\nThe default minimum log level is `info`. Users need to specifically set this property to `debug` to get *all* log entries.\nIt is RECOMMENDED that users set the level at least to \"warning\" in production workflows.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "default": "info", + "example": "warning" + }, + "min_log_level_update": { + "description": "Updates the minimum severity level for log entries that the back-end stores for the processing requests.\n\nThe back-end doesn't need to update existing log entries.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "example": "warning" + }, + "data_type_schema": { + "title": "Data Types", + "description": "Either a single data type or a list of data types.", + "oneOf": [ + { + "$ref": "#/components/schemas/process_json_schema" + }, + { + "title": "Multiple data types", + "description": "A list of data types this parameter supports, specified as JSON Schemas.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/process_json_schema" + } + } + ] + }, + "process_schema": { + "title": "Process Data types", + "description": "Either a single data type or a list of data types for process parameter or process return values.", + "oneOf": [ + { + "$ref": "#/components/schemas/process_json_schema" + }, + { + "title": "Multiple data types", + "description": "A list of data types supported, specified as JSON Schemas.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/process_json_schema" + } + } + ] + }, + "process_json_schema": { + "type": "object", + "title": "Single Data Type", + "description": "Specifies a data type supported by a parameter or return value.\n\nThe data types are specified according to the [JSON Schema draft-07](http://json-schema.org/) specification.\nSee the chapter ['Schemas' in 'Defining Processes'](#section/Processes/Defining-Processes) for more information.\n\nJSON Schemas SHOULD NOT contain `default`, `anyOf`, `oneOf`, `allOf` or `not` at the top-level of the schema.\nInstead specify each data type in a separate array element.\n\nThe following more complex JSON Schema keywords SHOULD NOT be used:\n`if`, `then`, `else`, `readOnly`, `writeOnly`, `dependencies`, `minProperties`, `maxProperties`, `patternProperties`.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved). This allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema is only a common subset of JSON Schema. Additional keywords MAY be used.", + "properties": { + "subtype": { + "type": "string", + "description": "The allowed sub data type for a value. See the chapter on [subtypes](#section/Processes/Defining-Processes) for more information." + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/json_schema" + } + ], + "oneOf": [ + { + "title": "Generic" + }, + { + "$ref": "#/components/schemas/process_graph_json_schema" + }, + { + "$ref": "#/components/schemas/datacube_json_schema" + } + ] + }, + "process_graph_json_schema": { + "title": "Process Graph", + "type": "object", + "properties": { + "subtype": { + "type": "string", + "enum": [ + "process-graph" + ] + }, + "parameters": { + "type": "array", + "title": "Process Graph Parameters", + "description": "A list of parameters passed to the child process graph.\n\nThe order in the array corresponds to the parameter order to\nbe used in clients that don't support named parameters.", + "items": { + "$ref": "#/components/schemas/parameter" + } + }, + "returns": { + "type": "object", + "title": "Process Graph Return Value", + "description": "Description of the data that is returned by the child process graph.", + "required": [ + "schema" + ], + "properties": { + "description": { + "$ref": "#/components/schemas/process_description" + }, + "schema": { + "$ref": "#/components/schemas/data_type_schema" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/process_json_schema" + } + ] + } + } + }, + "datacube_json_schema": { + "title": "Datacube", + "properties": { + "subtype": { + "type": "string", + "enum": [ + "datacube" + ] + }, + "dimensions": { + "title": "Datacube constraints", + "description": "Allows to specify requirements the data cube has to fulfill.\nRight now, it only allows to specify the dimension types and \nadds for specific dimension types:\n* axes for `spatial` dimensions in raster datacubes\n* geometry types for `geometry` dimensions in vector datacubes", + "type": "array", + "items": { + "type": "object", + "required": [ + "type" + ], + "oneOf": [ + { + "title": "Spatial (raster)", + "properties": { + "type": { + "type": "string", + "enum": [ + "spatial" + ] + }, + "axis": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/dimension_axis_xyz" + } + } + } + }, + { + "title": "Spatial (vector)", + "properties": { + "type": { + "type": "string", + "enum": [ + "geometry" + ] + }, + "geometry_type": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/geometry_type" + } + } + } + }, + { + "title": "Other", + "properties": { + "type": { + "type": "string", + "enum": [ + "bands", + "temporal", + "other" + ] + } + } + } + ] + } + } + } + }, + "json_schema": { + "type": "object", + "title": "JSON Schema", + "description": "A JSON Schema compliant to [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html) or later.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved).\nThis allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema in the OpenAPI document is only a common subset of JSON Schema.\nAdditional keywords from the JSON Schema specification MAY be used.", + "properties": { + "$schema": { + "description": "The JSON Schema version. If not given in the context of openEO,\ndefaults to `draft-07`.\n\nYou may need to add the default value for `$schema` property explicitly to the JSON Schema\nobject before passing it to a JSON Schema validator.", + "type": "string", + "format": "uri", + "default": "http://json-schema.org/draft-07/schema#" + }, + "$id": { + "description": "ID of your JSON Schema.", + "type": "string", + "format": "uri" + }, + "type": { + "description": "The allowed basic data type(s) for a value.\n\nIf this property is not present, all data types are allowed.", + "oneOf": [ + { + "$ref": "#/components/schemas/json_schema_type" + }, + { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/json_schema_type" + } + } + ] + }, + "pattern": { + "type": "string", + "format": "regex", + "description": "The regular expression a string value must match against." + }, + "enum": { + "type": "array", + "items": {}, + "description": "An exclusive list of allowed values." + }, + "minimum": { + "type": "number", + "description": "The minimum value (inclusive) allowed for a numerical value." + }, + "maximum": { + "type": "number", + "description": "The maximum value (inclusive) allowed for a numerical value." + }, + "minItems": { + "type": "number", + "minimum": 0, + "default": 0, + "description": "The minimum number of items required in an array." + }, + "maxItems": { + "type": "number", + "minimum": 0, + "description": "The maximum number of items required in an array." + }, + "items": { + "description": "Specifies schemas for the items in an array.", + "anyOf": [ + { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/json_schema" + } + }, + { + "$ref": "#/components/schemas/json_schema" + } + ] + } + }, + "additionalProperties": { + "description": "You can add any other property supported by the JSON Schema version that is given through the property `$schema`, so either [draft-07](https://json-schema.org/draft-07/json-schema-validation.html) or any later version." + } + }, + "json_schema_type": { + "type": "string", + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "file": { + "title": "Workspace File", + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string", + "description": "Path of the file, relative to the root directory of the user's server-side workspace.\nMUST NOT start with a slash `/` and MUST NOT be url-encoded.\n\nThe Windows-style path name component separator `\\` is not supported,\nalways use `/` instead.\n\nNote: The pattern only specifies a minimal subset of invalid characters.\nThe back-ends MAY enforce additional restrictions depending on their OS/environment.", + "example": "folder/file.txt", + "pattern": "^[^/\r\n\\:'\"][^\r\n\\:'\"]*$" + }, + "size": { + "type": "integer", + "description": "File size in bytes.", + "example": 1024 + }, + "modified": { + "type": "string", + "format": "date-time", + "description": "Date and time the file has lastly been modified, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2018-01-03T10:55:29Z" + } + } + }, + "geometry_type": { + "title": "Geometry type", + "type": "string", + "enum": [ + "Point", + "MultiPoint", + "LineString", + "MultiLineString", + "Polygon", + "MultiPolygon", + "GeometryCollection" + ] + }, + "GeoJsonPoint3D": { + "type": "array", + "description": "Point in 3D space", + "minItems": 2, + "maxItems": 3, + "items": { + "type": "number" + } + }, + "GeoJsonPoint": { + "type": "object", + "title": "GeoJSON Point", + "required": [ + "type", + "coordinates" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "Point" + ] + }, + "coordinates": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } + } + }, + "GeoJsonFeatureCollection": { + "type": "object", + "required": [ + "type", + "features" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "FeatureCollection" + ] + }, + "features": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonFeature" + } + } + } + }, + "GeoJsonFeature": { + "type": "object", + "required": [ + "type", + "geometry", + "properties" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "Feature" + ] + }, + "geometry": { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + "properties": { + "type": "object", + "nullable": true + } + } + }, + "GeoJson": { + "title": "GeoJSON", + "oneOf": [ + { + "$ref": "#/components/schemas/GeoJsonFeatureCollection" + }, + { + "$ref": "#/components/schemas/GeoJsonFeature" + }, + { + "$ref": "#/components/schemas/GeoJsonGeometry" + } + ] + }, + "GeoJsonGeometry": { + "title": "GeoJSON Geometry", + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "$ref": "#/components/schemas/geometry_type" + } + }, + "discriminator": { + "propertyName": "type", + "mapping": { + "Point": "#/components/schemas/GeoJsonPoint", + "LineString": "#/components/schemas/GeoJsonLineString", + "Polygon": "#/components/schemas/GeoJsonPolygon", + "MultiPoint": "#/components/schemas/GeoJsonMultiPoint", + "MultiLineString": "#/components/schemas/GeoJsonMultiLineString", + "MultiPolygon": "#/components/schemas/GeoJsonMultiPolygon", + "GeometryCollection": "#/components/schemas/GeoJsonGeometryCollection" + } + } + }, + "GeoJsonLineString": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + { + "type": "object", + "title": "GeoJSON LineString", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } + } + } + } + ] + }, + "GeoJsonPolygon": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + { + "type": "object", + "title": "GeoJSON Polygon", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } + } + } + } + } + ] + }, + "GeoJsonMultiPoint": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + { + "type": "object", + "title": "GeoJSON MultiPoint", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } + } + } + } + ] + }, + "GeoJsonMultiLineString": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + { + "type": "object", + "title": "GeoJSON MultiLineString", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } + } + } + } + } + ] + }, + "GeoJsonMultiPolygon": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + { + "type": "object", + "title": "GeoJSON MultiPolygon", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } + } + } + } + } + } + ] + }, + "GeoJsonGeometryCollection": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + { + "type": "object", + "title": "GeoJSON GeometryCollection", + "required": [ + "geometries" + ], + "properties": { + "geometries": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonGeometry" + } + } + } + } + ] + }, + "log_entry": { + "title": "Log Entry", + "description": "An log message that communicates information about the processed data.", + "type": "object", + "required": [ + "id", + "level", + "message" + ], + "properties": { + "id": { + "type": "string", + "description": "An unique identifier for the log message, could simply be an incrementing number.", + "example": "1" + }, + "code": { + "$ref": "#/components/schemas/log_code" + }, + "level": { + "$ref": "#/components/schemas/log_level" + }, + "message": { + "type": "string", + "description": "A concise message explaining the log entry.\nMessages do *not* explicitly support [CommonMark 0.29](http://commonmark.org/) syntax as other descriptive fields in the openEO API do, but the messages MAY contain line breaks or indentation.\nIt is NOT RECOMMENDED to add stacktraces to the `message`.", + "example": "Can't load the UDF file from the URL `https://openeo.example/invalid/file.txt`. Server responded with error 404." + }, + "time": { + "type": "string", + "format": "date-time", + "title": "Date and Time", + "description": "The date and time the event happened, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." + }, + "data": { + "description": "Data of any type. It is the back-ends task to decide how to best\npresent passed data to a user.\n\nFor example, a datacube passed to the `inspect` SHOULD return the\nmetadata similar to the collection metadata, including `cube:dimensions`.\nThere are implementation guidelines available for the `inspect` process." + }, + "path": { + "description": "Describes where the log entry originates from.\n\nThe first element of the array is the process that has triggered the log entry, the second element is the parent of the process that has triggered the log entry, etc. This pattern is followed until the root of the process graph.", + "type": "array", + "items": { + "type": "object", + "required": [ + "node_id" + ], + "properties": { + "node_id": { + "type": "string", + "description": "The id of the node the log entry originates from.", + "example": "runudf1" + }, + "process_id": { + "$ref": "#/components/schemas/process_id" + }, + "namespace": { + "$ref": "#/components/schemas/process_namespace" + }, + "parameter": { + "type": "string", + "description": "If applicable, the name of the parameter the log entry corresponds to.", + "pattern": "^\\w+$", + "nullable": true, + "example": "udf" + } + } + } + }, + "usage": { + "$ref": "#/components/schemas/usage" + }, + "links": { + "$ref": "#/components/schemas/log_links" + } + } + }, + "usage": { + "title": "Resource usage metrics", + "type": "object", + "properties": { + "cpu": { + "description": "Specifies the CPU usage, usually in a unit such as `cpu-seconds`.", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "memory": { + "description": "Specifies the memory usage, usually in a unit such as `mb-seconds` or `gb-hours`.", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "duration": { + "description": "Specifies the wall time, usually in a unit such as `seconds`, `minutes` or `hours`.", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "network": { + "description": "Specifies the network transfer usage (incoming and outgoing), usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "disk": { + "description": "Specifies the amount of input (read) and output (write) operations on the storage such as disks, usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "storage": { + "description": "Specifies the usage of storage space, usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + } + }, + "additionalProperties": { + "description": "Additional metrics.", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "example": { + "cpu": { + "value": 40668, + "unit": "cpu-seconds" + }, + "duration": { + "value": 2611, + "unit": "seconds" + }, + "memory": { + "value": 108138811, + "unit": "mb-seconds" + }, + "network": { + "value": 0, + "unit": "kb" + }, + "storage": { + "value": 55, + "unit": "mb" + } + } + }, + "usage_metric": { + "type": "object", + "required": [ + "value", + "unit" + ], + "properties": { + "value": { + "type": "number", + "minimum": 0 + }, + "unit": { + "type": "string" + } + } + } + }, + "responses": { + "logs": { + "description": "Lists the requested log entries.", + "content": { + "application/json": { + "schema": { + "title": "Log Entries", + "type": "object", + "required": [ + "logs", + "links" + ], + "properties": { + "level": { + "description": "The minimum severity level for log entries that the back-end returns.\nThis property MUST reflect the effective lowest `level` that may appear in the document,\nwhich is (if implemented) the highest level of:\n1. the `log_level` specified by the user for the processing request.\n2. the `level` specified by the user for the log request.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the logs will only contain entries with the level `warning` and `error`.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "default": "debug" + }, + "logs": { + "description": "A chronological list of logs.", + "type": "array", + "items": { + "$ref": "#/components/schemas/log_entry" + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + } + } + } + }, + "client_error": { + "description": "The request can't be fulfilled due to an error on client-side, i.e. the\nrequest is invalid. The client SHOULD NOT repeat the request without\nmodifications.\n\nThe response body SHOULD contain a JSON error object.\nMUST be any HTTP status code specified in [RFC\n7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6). This request\nusually does not respond with HTTP status codes 401 and 403 due to\nmissing authorization. HTTP status code 404 SHOULD be used if the value\nof a path parameter is invalid.\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "client_error_auth": { + "description": "The request can't be fulfilled due to an error on client-side, i.e. the\nrequest is invalid. The client SHOULD NOT repeat the request without\nmodifications.\n\nThe response body SHOULD contain a JSON error object.\nMUST be any HTTP status code specified in [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6).\nThis request MUST respond with HTTP status codes 401 if authorization is required or\n403 if the authorization failed or access is forbidden in general to the\nauthenticated user. HTTP status code 404 SHOULD be used if the value of\na path parameter is invalid.\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "server_error": { + "description": "The request can't be fulfilled due to an error at the back-end. The\nerror is never the client\u2019s fault and therefore it is reasonable for the\nclient to retry the exact same request that triggered this response.\n\nThe response body SHOULD contain a JSON error object. MUST be any HTTP\nstatus code specified in [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6).\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + } + }, + "parameters": { + "pagination_limit": { + "name": "limit", + "description": "This parameter enables pagination for the endpoint and specifies the maximum number of\nelements that arrays in the top-level object (e.g. collections, processes, batch jobs,\nsecondary services, log entries, etc.) are allowed to contain.\nThe `links` array MUST NOT be paginated like the resources,\nbut instead contain links related to the paginated resources\nor the pagination itself (e.g. a link to the next page).\nIf the parameter is not provided or empty, all elements are returned.\n\nPagination is OPTIONAL: back-ends or clients may not support it.\nTherefore it MUST be implemented in a way that clients not supporting\npagination get all resources regardless. Back-ends not supporting\npagination MUST return all resources.\n\nIf the response is paginated, the `links` array MUST be used to communicate the\nlinks for browsing the pagination with predefined `rel` types. See the `links` array schema\nfor supported `rel` types.\nBack-end implementations can, unless specified otherwise, use all kind of pagination techniques,\ndepending on what is supported best by their infrastructure: page-based, offset-based, token-based\nor something else. The clients SHOULD use whatever is specified\nin the links with the corresponding `rel` types.", + "in": "query", + "allowEmptyValue": true, + "example": 10, + "schema": { + "type": "integer", + "minimum": 1 + } + }, + "log_offset": { + "name": "offset", + "description": "The last identifier (property `id` of a log entry) the client has received. If provided, the back-ends only sends the entries that occurred after the specified identifier. If not provided or empty, start with the first entry.", + "in": "query", + "allowEmptyValue": true, + "example": "log1234", + "schema": { + "type": "string" + } + }, + "log_level": { + "name": "level", + "description": "The minimum severity level for log entries that the back-end returns.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the back-end will only return log entries with the level `warning` and `error`.\n\nThe default minimum log level is `debug`, which returns all log levels.", + "in": "query", + "allowEmptyValue": true, + "example": "error", + "schema": { + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "default": "info" + } + }, + "service_id": { + "name": "service_id", + "in": "path", + "description": "Identifier of the secondary web service.", + "required": true, + "schema": { + "$ref": "#/components/schemas/service_id" + } + }, + "job_id": { + "name": "job_id", + "in": "path", + "description": "Identifier of the batch job.", + "required": true, + "schema": { + "$ref": "#/components/schemas/job_id" + } + }, + "collection_id": { + "name": "collection_id", + "in": "path", + "description": "Collection identifier", + "required": true, + "schema": { + "$ref": "#/components/schemas/collection_id" + } + } + }, + "examples": { + "evi_user_defined_process": { + "description": "A user-defined process that computes the EVI.", + "value": { + "id": "evi", + "summary": "Enhanced Vegetation Index", + "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", + "parameters": [ + { + "name": "red", + "description": "Value from the red band.", + "schema": { + "type": "number" + } + }, + { + "name": "blue", + "description": "Value from the blue band.", + "schema": { + "type": "number" + } + }, + { + "name": "nir", + "description": "Value from the near infrared band.", + "schema": { + "type": "number" + } + } + ], + "returns": { + "description": "Computed EVI.", + "schema": { + "type": "number" + } + }, + "process_graph": { + "sub": { + "process_id": "subtract", + "arguments": { + "x": { + "from_parameter": "nir" + }, + "y": { + "from_parameter": "red" + } + } + }, + "p1": { + "process_id": "multiply", + "arguments": { + "x": 6, + "y": { + "from_parameter": "red" + } + } + }, + "p2": { + "process_id": "multiply", + "arguments": { + "x": -7.5, + "y": { + "from_parameter": "blue" + } + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_parameter": "nir" + }, + { + "from_node": "p1" + }, + { + "from_node": "p2" + } + ] + } + }, + "div": { + "process_id": "divide", + "arguments": { + "x": { + "from_node": "sub" + }, + "y": { + "from_node": "sum" + } + } + }, + "p3": { + "process_id": "multiply", + "arguments": { + "x": 2.5, + "y": { + "from_node": "div" + } + }, + "result": true + } + } + } + } + }, + "securitySchemes": { + "Bearer": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "The Bearer Token MUST consist of the authentication method, a provider ID (if available) and the token itself. All separated by a forward slash `/`. Examples (replace `TOKEN` with the actual access token): (1) Basic authentication (no provider ID available): `basic//TOKEN` (2) OpenID Connect (provider ID is `ms`): `oidc/ms/TOKEN`. For OpenID Connect, the provider ID corresponds to the value specified for `id` for each provider in `GET /credentials/oidc`." + }, + "Basic": { + "type": "http", + "scheme": "basic" + } + } + } +} \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/test_compliance.py b/src/openeo_test_suite/tests/general/test_compliance.py new file mode 100644 index 0000000..8351576 --- /dev/null +++ b/src/openeo_test_suite/tests/general/test_compliance.py @@ -0,0 +1,1497 @@ +from openapi_core import Spec +import pytest +import requests +import openeo_test_suite.tests.general.compliance_util as conformance_util +import uuid + + +# region Test Fixtures + + +@pytest.fixture(scope="session") +def base_url(request): + return conformance_util.get_base_url(request=request) + + +@pytest.fixture(scope="session") +def domain(request): + return conformance_util.get_domain(request=request) + + +@pytest.fixture(scope="session") +def spec(request): + return conformance_util.adjust_spec_json( + conformance_util.get_spec_path_json(), conformance_util.get_base_url(request) + ) + + +@pytest.fixture(scope="session") +def bearer_token(): + bearer_token = conformance_util.get_access_token() + return f"Bearer oidc/egi/{bearer_token}" + + +# endregion + +# region Test Implementations + + +def test_GET_backend_info(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "" + test_name = "Backend Info" + + # Run through all the generic GET endpoints and test their response to a proper request. + + fail_log = conformance_util.test_endpoint( + base_url=base_url, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_well_known(domain: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: Change server in spec + testing: test response by API for GET requests + cleanup: Change server back potentially + """ + spec = conformance_util.adjust_spec_well_known_json( + conformance_util.get_spec_path_json(), domain + ) + + endpoint_path = ".well-known/openeo" + test_name = "Well known" + + # Run through all the generic GET endpoints and test their response to a proper request. + + fail_log = conformance_util.test_endpoint( + base_url=domain, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_file_formats(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "file_formats" + test_name = "File formats" + + # Run through all the generic GET endpoints and test their response to a proper request. + fail_log = conformance_util.test_endpoint( + base_url=base_url, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_conformance(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "conformance" + test_name = "Conformance" + + # Run through all the generic GET endpoints and test their response to a proper request. + fail_log = conformance_util.test_endpoint( + base_url=base_url, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_udf_runtimes(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "udf_runtimes" + test_name = "UDF runtimes" + + fail_log = conformance_util.test_endpoint( + base_url=base_url, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_service_types(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "service_types" + test_name = "Service Types" + + fail_log = conformance_util.test_endpoint( + base_url=base_url, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_credentials_oidc(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "credentials/oidc" + test_name = "OpenID Connect authentication" + + fail_log = conformance_util.test_endpoint( + base_url=base_url, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_collections(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "collections" + test_name = "Basic metadata for all collections" + + fail_log = conformance_util.test_endpoint( + base_url=base_url, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_processes(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "processes" + test_name = "List of Predefined Processes" + + fail_log = conformance_util.test_endpoint( + base_url=base_url, endpoint_path=endpoint_path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_me(base_url: str, spec: Spec, bearer_token: str): + """ + tests all the generic GET endpoints that require neither setup nor cleanup + + setup: None + testing: test response by API for GET requests + cleanup: None + + """ + endpoint_path = "me" + test_name = "Information about logged in user" + + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + ) + + assert fail_log == "" + + +def test_GET_collections_collection_id(base_url: str, spec: Spec, bearer_token: str): + """ + setup: collect list of collection ids + testing: test response by API for GET requests of all the collection ids + cleanup: None + + """ + fail_log = "" + + collection_ids = [ + collection["id"] + for collection in requests.get((f"{base_url}collections")).json()["collections"] + ] + + # prepare list of endpoints + special_GET_endpoints_no_auth = [ + (f"collections/{collection_id}", f"Test for collection/{collection_id}") + for collection_id in collection_ids + ] + + # Run through all the special GET endpoints and test their response to a proper request. + for path, test_name in special_GET_endpoints_no_auth: + fail_log += conformance_util.test_endpoint( + base_url=base_url, endpoint_path=path, test_name=test_name, spec=spec + ) + + assert fail_log == "" + + +def test_GET_collections_collection_id_queryables( + base_url: str, spec: Spec, bearer_token: str +): + raise NotImplementedError() + + +def test_GET_process_graphs(base_url: str, spec: Spec, bearer_token: str): + """ + setup: submit valid user defined processes + testing: test response format of submitted user defined processes + cleanup: delete submitted user defined processes + """ + fail_log = "" + # SETUP + + endpoint_path = "process_graphs" + test_name = "List all user-defined processes" + + created_udp_ids = conformance_util.put_process_graphs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + ) + + # CLEANUP + + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_udp_ids, + ) + + assert fail_log == "" + + +def test_GET_process_graphs_process_id(base_url: str, spec: Spec, bearer_token: str): + """ + setup: submit user defined processes, gather list of user defined processes + testing: test each individual metadata response for submitted user-defined processes + cleanup: delete user defined processes + """ + # SETUP + fail_log = "" + + endpoint_path = "process_graphs" + + created_udp_ids = conformance_util.put_process_graphs( + base_url=base_url, bearer_token=bearer_token + ) + + # prepare list of endpoints + process_GET_endpoints_auth = [ + (f"{endpoint_path}/{process_id}", f"Test for {endpoint_path}/{process_id}") + for process_id in created_udp_ids + ] + + # TESTING + for prepared_endpoint_path, test_name in process_GET_endpoints_auth: + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + ) + + # CLEANUP + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_udp_ids, + ) + + assert fail_log == "" + + +def test_PUT_process_graphs_process_id(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: load payloads + TESTING: PUT UDPs + CLEANUP: DELETE UDPs + """ + + fail_log = "" + + # SETUP + endpoint_path = "process_graphs" + directory_path = conformance_util.get_examples_path() + examples_directory = "put_process_graphs" + + test_name = "Store a user-defined process" + + created_udp_ids = [] + payloads = conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + + # TESTING + for payload in payloads: + id = str(uuid.uuid4()) + created_udp_ids.append(id) + prepared_endpoint_path = f"{endpoint_path}/{id}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {id}", + spec=spec, + payload=payload, + bearer_token=bearer_token, + method="PUT", + ) + + # CLEANUP + + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_udp_ids, + ) + + assert fail_log == "" + + +def test_DELETE_process_graphs_process_id(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: PUT UDPs + TESTING: DELETE UDPs + CLEANUP: None + """ + fail_log = "" + + # SETUP + endpoint_path = "process_graphs" + + created_udp_ids = conformance_util.put_process_graphs( + base_url=base_url, bearer_token=bearer_token + ) + + process_graphs_DELETE_endpoints = [ + (f"{endpoint_path}/{process_id}", f"Test for {endpoint_path}/{process_id}") + for process_id in created_udp_ids + ] + + # TESTING + for prepared_endpoint_path, test_name in process_graphs_DELETE_endpoints: + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + method="DELETE", + expected_status_code=204, + ) + + # CLEANUP + + assert fail_log == "" + + +def test_GET_jobs(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: post jobs + TESTING: GET JOBS + CLEANUP: DELETE JOBS + """ + fail_log = "" + + # SETUP + endpoint_path = "jobs" + test_name = "List all batchjobs" + + created_batch_job_ids = conformance_util.post_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=f"{test_name}", + spec=spec, + bearer_token=bearer_token, + method="GET", + ) + + # CLEANUP + + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + + assert fail_log == "" + + +def test_POST_jobs(base_url: str, spec: Spec, bearer_token: str): + """ + setup: prepare batch jobs payloads + testing: test posting prepared batch jobs to endpoint + cleanup: delete posted batch jobs + """ + fail_log = "" + # SETUP + endpoint_path = "jobs" + test_name = "Creates a new batch processing task" + directory_path = conformance_util.get_examples_path() + examples_directory = "post_jobs" + + created_batch_job_ids = [] + + payloads = conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + + # TESTING + for payload in payloads: + _, payload = conformance_util.set_uuid_in_job(payload) + + fail_log_entry, response = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=payload, + method="POST", + expected_status_code=201, + return_response=True, + ) + + fail_log += fail_log_entry + created_batch_job_ids.append(response.headers["OpenEO-Identifier"]) + + # CLEANUP + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + + assert fail_log == "" + + +def test_GET_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: post jobs + TESTING: GET job metadata of posted jobs + CLEANUP: Delete jobs + """ + fail_log = "" + # SETUP + + endpoint_path = "jobs" + test_name = "Full metadata for a batch job" + + created_batch_job_ids = conformance_util.post_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + + for job_id in created_batch_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + method="GET", + ) + + # CLEANUP + + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + + assert fail_log == "" + + +def test_PATCH_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: POST jobs, prepare payloads + TESTING: PATCH jobs + CLEANUP: DELETE jobs + """ + fail_log = "" + # SETUP + + endpoint_path = "jobs" + test_name = "Modify a batch job" + + created_batch_job_ids = conformance_util.post_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + directory_path = conformance_util.get_examples_path() + examples_directory = "patch_jobs" + + payloads = conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + + # TESTING + + for job_id, payload in zip(created_batch_job_ids, payloads): + prepared_endpoint_path = f"{endpoint_path}/{job_id}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + payload=payload, + method="PATCH", + expected_status_code=204, + ) + + # CLEANUP + + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + + assert fail_log == "" + + +def test_DELETE_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): + """ + setup: Post jobs + testing: Delete posted jobs + cleanup: None + """ + fail_log = "" + # SETUP + endpoint_path = "jobs" + test_name = "Delete specific batch job" + + created_job_ids = conformance_util.post_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + + for job_id in created_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + method="DELETE", + expected_status_code=204, + ) + + # CLEANUP + + assert fail_log == "" + + +def test_POST_jobs_job_id_results(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: post jobs + TESTING: start batch jobs + CLEANUP: ?? + """ + # SETUP + fail_log = "" + + endpoint_path = "jobs" + endpoint_path_extra = "results" + test_name = "Start processing a batch job" + + created_batch_job_ids = conformance_util.post_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + + for job_id in created_batch_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}/{endpoint_path_extra}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + method="POST", + expected_status_code=202, + ) + + # CLEANUP + + try: + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + except Exception as e: + print(e) + + assert fail_log == "" + + +@pytest.mark.vv +@pytest.mark.skip( + reason="Takes too long for normal test runs, this decorator can be removed when fully testing is relevant" +) +def test_GET_jobs_job_id_results(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: POST jobs, START jobs (POST jobs/job_id/results), Wait for jobs to be finished + TESTING: GET job results + CLEANUP: DELETE Jobs + """ + fail_log = "" + # SETUP + endpoint_path = "jobs" + endpoint_path_extra = "results" + test_name = "Download results for a completed batch job" + + created_batch_job_ids = conformance_util.post_start_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + + conformance_util.wait_job_statuses( + base_url=base_url, + bearer_token=bearer_token, + job_ids=created_batch_job_ids, + job_statuses=["finished"], + timeout=160, + ) + + for job_id in created_batch_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}/{endpoint_path_extra}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + method="GET", + ) + + # CLEANUP + + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + + assert fail_log == "" + + +def test_DELETE_jobs_job_id_results(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: POST jobs, Start processing jobs + TESTING: DELETE job id results: Cancel processing jobs + CLEANUP: Delete jobs + """ + fail_log = "" + # SETUP + endpoint_path = "jobs" + endpoint_path_extra = "results" + test_name = "Cancel processing a batch job" + + created_batch_job_ids = conformance_util.post_start_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + conformance_util.wait_job_statuses( + base_url=base_url, + bearer_token=bearer_token, + job_ids=created_batch_job_ids, + job_statuses=["queued", "running"], + timeout=120, + ) + + # TESTING + + for job_id in created_batch_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}/{endpoint_path_extra}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + method="DELETE", + expected_status_code=204, + ) + + # CLEANUP + + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + + assert fail_log == "" + + +def test_GET_jobs_job_id_estimate(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: POST jobs, start jobs + TESTING: GET estimates for jobs + CLEANUP: Cancel and delete jobs + """ + + fail_log = "" + + # SETUP + endpoint_path = "jobs" + endpoint_path_extra = "estimate" + test_name = "Get an estimate for a running job" + + created_batch_job_ids = conformance_util.post_start_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + + for job_id in created_batch_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}/{endpoint_path_extra}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + method="GET", + ) + + # CLEANUP + + conformance_util.cancel_delete_jobs( + base_url=base_url, bearer_token=bearer_token, job_ids=created_batch_job_ids + ) + + assert fail_log == "" + + +def test_GET_jobs_job_id_logs(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: POST jobs, (start? jobs) + TESTING: GET logs for batch jobs, GET logs for batch jobs using offset + CLEANUP: (cancel? jobs), DELETE jobs + """ + fail_log = "" + # SETUP + + endpoint_path = "jobs" + endpoint_path_extra = "logs" + test_name = "Logs for a batch job" + + created_batch_job_ids = conformance_util.post_start_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + + for job_id in created_batch_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}/{endpoint_path_extra}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + method="GET", + ) + # CLEANUP + + conformance_util.cancel_delete_jobs( + base_url=base_url, bearer_token=bearer_token, job_ids=created_batch_job_ids + ) + + assert fail_log == "" + + +@pytest.mark.skip( + reason="Takes too long for normal test runs, this decorator can be removed when fully testing is relevant" +) +def test_POST_result(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: gather payloads + TESTING: POST payloads to result + CLEANUP: None + """ + fail_log = "" + + # SETUP + + endpoint_path = "result" + test_name = "Process and download data synchronously" + + directory_path = conformance_util.get_examples_path() + examples_directory = "post_result" + + payloads = conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + + # TESTING + + for payload in payloads: + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=payload, + method="POST", + expected_status_code=201, + ) + # CLEANUP + + assert fail_log == "" + + +def test_POST_validation(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: load payloads + TESTING: POST payloads for validation + CLEANUP: None + """ + + fail_log = "" + # SETUP + + endpoint_path = "validation" + test_name = "Validate a user-defined process (graph)" + + directory_path = conformance_util.get_examples_path() + examples_directory = "post_validation" + + payloads = conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + + # TESTING + + for payload in payloads: + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=payload, + method="POST", + ) + + # CLEANUP + + assert fail_log == "" + + +# endregion + +# region Negative Test Implementations + + +def test_none_PUT_process_graphs_process_id( + base_url: str, spec: Spec, bearer_token: str +): + """ + SETUP: load empty payloads + TESTING: PUT empty UDPs + CLEANUP: None + """ + fail_log = "" + # SETUP + + endpoint_path = "process_graphs" + + test_name = "Store a user-defined process (NEGATIVE)" + + # TESTING + + id = str(uuid.uuid4()) + prepared_endpoint_path = f"{endpoint_path}/{id}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {id}", + spec=spec, + payload=None, + bearer_token=bearer_token, + method="PUT", + expected_status_code=422, + ) + + # CLEANUP + + assert fail_log == "" + + +def test_negative_DELETE_process_graphs_process_id( + base_url: str, spec: Spec, bearer_token: str +): + """ + SETUP: None + TESTING: try DELETE non-existant UDPs + CLEANUP: None + """ + fail_log = "" + # SETUP + + endpoint = "process_graphs" + prepared_endpoint_path = f"{endpoint}/thisiddoesnotexist" + test_name = "Negative delete process graphs process id" + + # TESTING + + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + method="DELETE", + expected_status_code=500, + ) + + # CLEANUP + assert fail_log == "" + + +def test_none_POST_jobs(base_url: str, spec: Spec, bearer_token: str): + """ + setup: prepare empty payloads + testing: test posting empty payloads endpoint + cleanup: None + """ + # SETUP + endpoint_path = "jobs" + test_name = "Creates a new batch processing task (NEGATIVE)" + + # TESTING + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=None, + method="POST", + expected_status_code=422, + ) + + # CLEANUP + assert fail_log == "" + + +def test_none_PATCH_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: POST jobs, prepare payloads + TESTING: PATCH jobs with empty payload + CLEANUP: DELETE jobs + """ + + # SETUP + fail_log = "" + endpoint_path = "jobs" + test_name = "Negative Modify a batch job" + + created_batch_job_ids = conformance_util.post_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + # TESTING + for job_id in created_batch_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + payload=None, + method="PATCH", + expected_status_code=422, + ) + + # CLEANUP + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + + assert fail_log == "" + + +def test_negative_DELETE_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): + """ + setup: None + testing: Delete non-existent posted jobs + cleanup: None + """ + # SETUP + endpoint_path = "jobs" + test_name = "Delete specific batch job (NEGATIVE)" + + # TESTING + prepared_endpoint_path = f"{endpoint_path}/thisiddoesnotexist" + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} for non-existant id", + spec=spec, + bearer_token=bearer_token, + method="DELETE", + expected_status_code=422, + ) + + # CLEANUP + assert fail_log == "" + + +def test_negative_POST_jobs_job_id_results( + base_url: str, spec: Spec, bearer_token: str +): + """ + SETUP: None + TESTING: start batch jobs that doesn't exist + CLEANUP: None + """ + # SETUP + endpoint_path = "jobs" + endpoint_path_extra = "results" + test_name = "Start processing a batch job that doesn't exist" + + # TESTING + prepared_endpoint_path = f"{endpoint_path}/thisiddoesnotexist/{endpoint_path_extra}" + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name}", + spec=spec, + bearer_token=bearer_token, + method="POST", + expected_status_code=422, + ) + + # CLEANUP + assert fail_log == "" + + +def test_negative_GET_jobs_job_id_results(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: POST jobs, START jobs (POST jobs/job_id/results), Wait for jobs to be finished + TESTING: GET job results + CLEANUP: DELETE Jobs + """ + # SETUP + endpoint_path = "jobs" + endpoint_path_extra = "results" + test_name = "Download results for a completed batch job that doesn't exist" + + # TESTING + prepared_endpoint_path = f"{endpoint_path}/thisiddoesnotexist/{endpoint_path_extra}" + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name}", + spec=spec, + bearer_token=bearer_token, + method="GET", + expected_status_code=422, + ) + + # CLEANUP + assert fail_log == "" + + +def test_negative_DELETE_jobs_job_id_results( + base_url: str, spec: Spec, bearer_token: str +): + """ + SETUP: + TESTING: DELETE job id results: Cancel processing jobs + CLEANUP: None + """ + # SETUP + endpoint_path = "jobs" + endpoint_path_extra = "results" + test_name = "Cancel processing a batch job that doesn't exist" + + # TESTING + prepared_endpoint_path = f"{endpoint_path}/thisiddoesnotexist/{endpoint_path_extra}" + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name}", + spec=spec, + bearer_token=bearer_token, + method="DELETE", + expected_status_code=422, + ) + + # CLEANUP + assert fail_log == "" + + +def test_negative_GET_jobs_job_id_logs(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: None + TESTING: GET logs for batch jobs that don't exist + CLEANUP: + """ + # SETUP + + endpoint_path = "jobs" + endpoint_path_extra = "logs" + test_name = "Logs for a batch job" + + # TESTING + + prepared_endpoint_path = f"{endpoint_path}/thisiddoesnotexist/{endpoint_path_extra}" + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name}", + spec=spec, + bearer_token=bearer_token, + method="GET", + expected_status_code=422, + ) + # CLEANUP + + assert fail_log == "" + + +@pytest.mark.skip( + reason="Takes too long for normal test runs, this decorator can be removed when fully testing is relevant" +) +def test_none_POST_result(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: gather payloads + TESTING: POST empty payloads to result + CLEANUP: None + """ + # SETUP + + endpoint_path = "result" + test_name = "Process and download data synchronously" + + # TESTING + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=None, + method="POST", + expected_status_code=422, + ) + # CLEANUP + + assert fail_log == "" + + +def test_none_POST_validation(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: load empty payloads + TESTING: POST empty payloads for validation + CLEANUP: None + """ + + # SETUP + endpoint_path = "validation" + test_name = "Validate a user-defined process (graph)" + + # TESTING + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=None, + method="POST", + expected_status_code=422, + ) + + # CLEANUP + assert fail_log == "" + + +def test_empty_PUT_process_graphs_process_id( + base_url: str, spec: Spec, bearer_token: str +): + """ + SETUP: load empty payloads + TESTING: PUT empty UDPs + CLEANUP: None + """ + fail_log = "" + # SETUP + + endpoint_path = "process_graphs" + + test_name = "Store a user-defined process (EMPTY)" + + directory_path = conformance_util.get_examples_path() + examples_directory = "empty_payload" + + payload = next( + conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + ) + + # TESTING + + id = str(uuid.uuid4()) + prepared_endpoint_path = f"{endpoint_path}/{id}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {id}", + spec=spec, + payload=payload, + bearer_token=bearer_token, + method="PUT", + expected_status_code=500, + ) + + # CLEANUP + + assert fail_log == "" + + +def test_empty_POST_jobs(base_url: str, spec: Spec, bearer_token: str): + """ + setup: prepare empty payloads + testing: test posting empty payloads endpoint + cleanup: None + """ + # SETUP + endpoint_path = "jobs" + test_name = "Creates a new batch processing task (NEGATIVE)" + directory_path = conformance_util.get_examples_path() + examples_directory = "empty_payload" + + payload = next( + conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + ) + + # TESTING + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=payload, + method="POST", + expected_status_code=500, + ) + + # CLEANUP + assert fail_log == "" + + +def test_empty_PATCH_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: POST jobs, prepare payloads + TESTING: PATCH jobs with empty payload + CLEANUP: DELETE jobs + """ + + # SETUP + fail_log = "" + endpoint_path = "jobs" + test_name = "Negative Modify a batch job" + + created_batch_job_ids = conformance_util.post_jobs( + base_url=base_url, bearer_token=bearer_token + ) + + directory_path = conformance_util.get_examples_path() + examples_directory = "empty_payload" + + payload = next( + conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + ) + + # TESTING + for job_id in created_batch_job_ids: + prepared_endpoint_path = f"{endpoint_path}/{job_id}" + fail_log += conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=prepared_endpoint_path, + test_name=f"{test_name} {job_id}", + spec=spec, + bearer_token=bearer_token, + payload=payload, + method="PATCH", + expected_status_code=204, + ) + + # CLEANUP + conformance_util.delete_id_resource( + base_url=base_url, + endpoint_path=endpoint_path, + bearer_token=bearer_token, + ids=created_batch_job_ids, + ) + + assert fail_log == "" + + +@pytest.mark.skip( + reason="Takes too long for normal test runs, this decorator can be removed when fully testing is relevant" +) +def test_empty_POST_result(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: gather payloads + TESTING: POST empty payloads to result + CLEANUP: None + """ + # SETUP + + endpoint_path = "result" + test_name = "Process and download data synchronously" + + directory_path = conformance_util.get_examples_path() + examples_directory = "empty_payload" + + payload = next( + conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + ) + # TESTING + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=payload, + method="POST", + expected_status_code=422, + ) + # CLEANUP + + assert fail_log == "" + + +def test_empty_POST_validation(base_url: str, spec: Spec, bearer_token: str): + """ + SETUP: load empty payloads + TESTING: POST empty payloads for validation + CLEANUP: None + """ + + # SETUP + endpoint_path = "validation" + test_name = "Validate a user-defined process (graph)" + + directory_path = conformance_util.get_examples_path() + examples_directory = "empty_payload" + + payload = next( + conformance_util.load_payloads_from_directory( + directory_path=f"{directory_path}/{examples_directory}" + ) + ) + + # TESTING + fail_log = conformance_util.test_endpoint( + base_url=base_url, + endpoint_path=endpoint_path, + test_name=test_name, + spec=spec, + bearer_token=bearer_token, + payload=payload, + method="POST", + expected_status_code=200, + ) + + # CLEANUP + assert fail_log == "" + + +# endregion From 2bd3a1c432bb8c22ccdab27959bb7409e74f04a1 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Wed, 31 Jan 2024 12:08:58 +0100 Subject: [PATCH 02/12] Integrate general API compliance checks --- .../tests/general/compliance_util.py | 112 +- .../tests/general/openapi.json | 12528 ++++++++-------- .../empty_payload/empty_payload.json | 1 + .../mock_processes/mock_processes_0.json | 133 + .../patch_jobs/patch_jobs_1.json | 342 + .../post_jobs/post_jobs_1.json | 41 + .../post_result/post_result_1.json | 340 + .../post_validation/post_validation_1.json | 103 + .../put_process_graphs_1.json | 103 + .../tests/general/test_compliance.py | 65 +- 10 files changed, 7401 insertions(+), 6367 deletions(-) create mode 100644 src/openeo_test_suite/tests/general/payload_examples/empty_payload/empty_payload.json create mode 100644 src/openeo_test_suite/tests/general/payload_examples/mock_processes/mock_processes_0.json create mode 100644 src/openeo_test_suite/tests/general/payload_examples/patch_jobs/patch_jobs_1.json create mode 100644 src/openeo_test_suite/tests/general/payload_examples/post_jobs/post_jobs_1.json create mode 100644 src/openeo_test_suite/tests/general/payload_examples/post_result/post_result_1.json create mode 100644 src/openeo_test_suite/tests/general/payload_examples/post_validation/post_validation_1.json create mode 100644 src/openeo_test_suite/tests/general/payload_examples/put_process_graphs/put_process_graphs_1.json diff --git a/src/openeo_test_suite/tests/general/compliance_util.py b/src/openeo_test_suite/tests/general/compliance_util.py index 3bbfa08..46683ae 100644 --- a/src/openeo_test_suite/tests/general/compliance_util.py +++ b/src/openeo_test_suite/tests/general/compliance_util.py @@ -1,3 +1,4 @@ +from typing import Union from openapi_core import Spec import yaml import json @@ -6,7 +7,10 @@ import requests import time -from openeo_test_suite.lib.backend_under_test import get_backend_url +from openeo_test_suite.lib.backend_under_test import ( + get_backend_url, + get_backend_under_test, +) from openapi_core import validate_response @@ -23,7 +27,7 @@ def test_endpoint( payload: dict = None, bearer_token: str = None, method: str = "GET", - expected_status_code: int = 200, + expected_status_codes: Union[list[int], int] = [200], return_response: bool = False, ): full_endpoint_url = f"{base_url}{endpoint_path}" @@ -115,14 +119,14 @@ def test_endpoint( openapi_response = RequestsOpenAPIResponse(requests_response) try: - if openapi_response.status_code == expected_status_code: + if check_status_code(expected_status_codes, openapi_response.status_code): validate_response( openapi_request, openapi_response, spec=spec, cls=V30ResponseValidator ) else: raise UnexpectedStatusCodeException( endpoint=full_endpoint_url, - expected_status_code=expected_status_code, + expected_status_code=expected_status_codes, actual_status_code=openapi_response.status_code, auth=(bearer_token is not None), ) @@ -139,6 +143,14 @@ def test_endpoint( return "" +def check_status_code( + expected_status_codes: Union[list[int], int], actual_status_code: int +): + if isinstance(expected_status_codes, int): + return actual_status_code == expected_status_codes + return actual_status_code in expected_status_codes + + class UnexpectedStatusCodeException(Exception): def __init__(self, endpoint, expected_status_code, actual_status_code, auth): self.endpoint = endpoint @@ -271,19 +283,6 @@ def check_test_results(e: Exception): # THIS IS A WORKAROUND, # this can be removed IF the cause of ServerNotFound Exception has been fixed -def adjust_server_in_yaml(path_to_yaml: str, endpoint: str): - with open(path_to_yaml, "r") as file: - data = yaml.safe_load(file) - - if "servers" in data and isinstance(data["servers"], list): - for server in data["servers"]: - if "url" in server and isinstance(server["url"], str): - server["url"] = endpoint - - with open(path_to_yaml, "w") as file: - yaml.dump(data, file) - - def adjust_server_in_json(path_to_json, endpoint): with open(path_to_json, "r") as file: data = json.load(file) @@ -292,45 +291,19 @@ def adjust_server_in_json(path_to_json, endpoint): for server in data["servers"]: if "url" in server and isinstance(server["url"], str): server["url"] = endpoint + return data - with open(path_to_json, "w") as file: - json.dump(data, file, indent=4) - - -# JSON variant -def adjust_spec_json(path_to_json: str, endpoint: str): - adjust_server_in_json(path_to_json=path_to_json, endpoint=endpoint) - - with open(path_to_json, "r") as file: - data = json.load(file) - return Spec.from_dict(data, validator=None) - - -def adjust_spec_well_known_json(path_to_json: str, endpoint: str): - adjust_server_in_well_known_json(path_to_json=path_to_json, endpoint=endpoint) - - with open(path_to_json, "r") as file: - data = json.load(file) - return Spec.from_dict(data, validator=None) +def adjust_spec_json(path_to_json: str, endpoint: str, domain: str): + data = adjust_server_in_json(path_to_json=path_to_json, endpoint=endpoint) + data = adjust_server_in_well_known_json(data=data, endpoint=domain) + return Spec.from_dict(data, validator=None) -def adjust_server_in_well_known_json(path_to_json, endpoint): - with open(path_to_json, "r") as file: - data = json.load(file) +def adjust_server_in_well_known_json(data, endpoint): data["paths"]["/.well-known/openeo"]["get"]["servers"][0]["url"] = endpoint - with open(path_to_json, "w") as file: - json.dump(data, file, indent=4) - - -# YAML variant -def adjust_spec_yaml(path_to_yaml: str, endpoint: str): - adjust_server_in_yaml(path_to_yaml=path_to_yaml, endpoint=endpoint) - - with open(path_to_yaml, "r") as file: - data = yaml.safe_load(file) - return Spec.from_dict(data, validator=None) + return data def validate_uri(value): @@ -352,17 +325,15 @@ def unmarshal_commonmark(value): def get_examples_path(): - return os.path.join(os.getcwd(), "openeo_conformance_test/payload_examples") + return os.path.join( + os.getcwd(), "src/openeo_test_suite/tests/general/payload_examples" + ) def get_spec_path_json(): return os.path.join(os.getcwd(), "src/openeo_test_suite/tests/general/openapi.json") -def get_process_list_path(): - return os.path.join(os.getcwd(), "tests/general/process_list.json") - - def load_payloads_from_directory(directory_path: str) -> list[dict]: for filename in os.listdir(directory_path): if filename.endswith(".json"): @@ -478,6 +449,13 @@ def post_start_jobs(base_url: str, bearer_token: str): full_endpoint_url = f"{base_url}/{endpoint_path}/{job_id}/{endpoint_path_extra}" requests.post(full_endpoint_url, headers={"Authorization": f"{bearer_token}"}) + wait_job_statuses( + base_url=base_url, + bearer_token=bearer_token, + job_ids=created_batch_job_ids, + job_statuses=["running"], + timeout=60, + ) return created_batch_job_ids @@ -490,7 +468,6 @@ def cancel_delete_jobs(base_url: str, bearer_token: str, job_ids: list[str]): for job_id in job_ids: full_endpoint_url = f"{base_url}/{endpoint_path}/{job_id}" - requests.delete(full_endpoint_url, headers={"Authorization": f"{bearer_token}"}) @@ -509,16 +486,15 @@ def get_process_list(base_url: str): return json.loads(requests.get(full_endpoint_url).content)["processes"] -def get_access_token(): +def get_access_token(pytestconfig): + backend = get_backend_under_test() + + capmanager = pytestconfig.pluginmanager.getplugin("capturemanager") + with capmanager.global_and_fixture_disabled(): + backend.connection.authenticate_oidc() # load_dotenv("..") - refresh_token = os.getenv("OIDC_EGI_REFRESH_TOKEN") - url = "https://aai.egi.eu/auth/realms/egi/protocol/openid-connect/token" - payload = f"grant_type=refresh_token&refresh_token={refresh_token}&client_id=token-portal&scope=openid%20email%20profile%20voperson_id%20eduperson_entitlement" - headers = {"Content-Type": "application/x-www-form-urlencoded"} - response = requests.post(url, data=payload, headers=headers) - - if response.status_code == 200: - return json.loads(response.content)["access_token"] + if hasattr(backend.connection.auth, "bearer"): + return backend.connection.auth.bearer return None @@ -544,15 +520,13 @@ def get_version(request): def get_base_url(request): url = get_backend_url(request.config) - if not url: - url = "https://openeo-dev.eodc.eu/" parsed_url = urlparse(url) # If the scheme is missing, add 'https://'. if not parsed_url.scheme: url = "https://" + url - # If the path is missing or doesn't contain 'openeo', query the '.well-known' endpoint. + # If the path is missing or doesn't contain 'openeo', query the '.well-known' endpoint. this is a failsafe. if not parsed_url.path or "openeo" not in parsed_url.path: requests_response = requests.get(url + "/.well-known/openeo") data = json.loads(requests_response.content) - url = data["versions"][0]["url"] + url = data["versions"][-1]["url"] return url diff --git a/src/openeo_test_suite/tests/general/openapi.json b/src/openeo_test_suite/tests/general/openapi.json index 7d77155..40275ed 100644 --- a/src/openeo_test_suite/tests/general/openapi.json +++ b/src/openeo_test_suite/tests/general/openapi.json @@ -1,6651 +1,6651 @@ { "openapi": "3.0.2", "info": { - "title": "openEO API", - "version": "1.2.0", - "description": "The openEO API specification for interoperable cloud-based processing of large Earth observation datasets.\n\n**Conformance class:** `https://api.openeo.org/1.2.0`\n\n# API Principles\n\n## Language\n\nIn the specification the key words \u201cMUST\u201d, \u201cMUST NOT\u201d, \u201cREQUIRED\u201d, \u201cSHALL\u201d, \u201cSHALL NOT\u201d, \u201cSHOULD\u201d, \u201cSHOULD NOT\u201d, \u201cRECOMMENDED\u201d, \u201cMAY\u201d, and \u201cOPTIONAL\u201d in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.html) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174.html).\n\n## Casing\n\nUnless otherwise stated the API works **case sensitive**.\n\nAll names SHOULD be written in snake case, i.e. words are separated with one underscore character (`_`) and no spaces, with all letters lower-cased. Example: `hello_world`. This applies particularly to endpoints and JSON property names. HTTP header fields are generally case-insensitive according to [RFC 7230](https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2) and in the specification we follow their respective casing conventions, e.g. `Content-Type` or `OpenEO-Costs`, for better readability and consistency.\n\n## HTTP / REST\n\nThis uses [HTTP REST](https://en.wikipedia.org/wiki/Representational_state_transfer) [Level 2](https://martinfowler.com/articles/richardsonMaturityModel.html#level2) for communication between client and back-end server.\n\nPublic APIs MUST be available via HTTPS only. \n\nEndpoints are made use meaningful HTTP verbs (e.g. GET, POST, PUT, PATCH, DELETE) whenever technically possible. If there is a need to transfer big chunks of data for a GET requests to the back-end, POST requests MAY be used as a replacement as they support to send data via request body. Unless otherwise stated, PATCH requests are only defined to work on direct (first-level) children of the full JSON object. Therefore, changing a property on a deeper level of the full JSON object always requires to send the whole JSON object defined by the first-level property.\n\nNaming of endpoints follow the REST principles. Therefore, endpoints are centered around resources. Resource identifiers MUST be named with a noun in plural form except for single actions that can not be modelled with the regular HTTP verbs. Single actions MUST be single endpoints with a single HTTP verb (POST is RECOMMENDED) and no other endpoints beneath it.\n\nThe openEO API makes use of [HTTP Content Negotiation](https://www.rfc-editor.org/rfc/rfc9110.html#name-content-negotiation),\nincluding, but not limited to, the request headers `Accept`, `Accept-Charset` and `Accept-Language`.\n\n### JSON\n\nThe API uses JSON for request and response bodies whenever feasible. Services use JSON as the default encoding. Other encodings can be requested using HTTP Content Negotiation ([`Accept` header](https://www.rfc-editor.org/rfc/rfc9110.html#name-accept)). Clients and servers MUST NOT rely on the order in which properties appear in JSON. To keep the response size small, lists of resources (e.g. the list of batch jobs) usually should not include nested JSON objects, if this information can be requested from the individual resource endpoints (e.g. the metadata for a single batch job).\n\n### Charset\n\nServices use [UTF-8](https://en.wikipedia.org/wiki/UTF-8) as the default charset if not negotiated otherwise with HTTP Content Negotiation ([`Accept-Charset` header](https://www.rfc-editor.org/rfc/rfc9110.html#name-accept-charset)).\n\n## Web Linking\n\nThe API is designed in a way that to most entities (e.g. collections and processes) a set of links can be added. These can be alternate representations, e.g. data discovery via OGC WCS or OGC CSW, references to a license, references to actual raw data for downloading, detailed information about pre-processing and more. Clients should allow users to follow the links.\n\nWhenever links are utilized in the API, the description explains which relation (`rel` property) types are commonly used.\nA [list of standardized link relations types is provided by IANA](https://www.iana.org/assignments/link-relations/link-relations.xhtml) and the API tries to align whenever feasible.\n\nSome very common relation types - usually not mentioned explicitly in the description of `links` fields - are:\n\n1. `self`: which allows link to the location that the resource can be (permanently) found online.This is particularly useful when the data is data is made available offline, so that the downstream user knows where the data has come from.\n\n2. `alternate`: An alternative representation of the resource, may it be another metadata standard the data is available in or simply a human-readable version in HTML or PDF.\n\n3. `about`: A resource that is related or further explains the resource, e.g. a user guide.\n\n4. `canonical`: This relation type usually points to a publicly accessible and more long-lived URL for a resource that otherwise often requires (Bearer) authentication with a short-lived token.\nThis way the the exposed resources can be used by non-openEO clients without additional authentication steps.\nFor example, a shared user-defined process or batch job results could be exposed via a canonical link.\nIf a URL should be publicly available to everyone, it can simply a user-specific URL, e.g. `https://openeo.example/processes/john_doe/ndvi`.\nFor resources that should only be accessible to a certain group of user, a signed URL could be given, e.g. `https://openeo.example/processes/81zjh1tc2pt52gbx/ndvi`.\n\nGenerally, it is RECOMMENDED to add descriptive titles (propertty `title`) and media type information (propertty `type`) for a better user experience.\n\n## Error Handling\n\nThe success of requests MUST be indicated using [HTTP status codes](https://www.rfc-editor.org/rfc/rfc7231.html#section-6) according to [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html).\n\nIf the API responds with a status code between 100 and 399 the back-end indicates that the request has been handled successfully.\n\nIn general an error is communicated with a status code between 400 and 599. Client errors are defined as a client passing invalid data to the service and the service *correctly* rejecting that data. Examples include invalid credentials, incorrect parameters, unknown versions, or similar. These are generally \"4xx\" HTTP error codes and are the result of a client passing incorrect or invalid data. Client errors do *not* contribute to overall API availability. \n\nServer errors are defined as the server failing to correctly return in response to a valid client request. These are generally \"5xx\" HTTP error codes. Server errors *do* contribute to the overall API availability. Calls that fail due to rate limiting or quota failures MUST NOT count as server errors. \n\n### JSON error object\n\nA JSON error object SHOULD be sent with all responses that have a status code between 400 and 599.\n\n``` json\n{\n \"id\": \"936DA01F-9ABD-4D9D-80C7-02AF85C822A8\",\n \"code\": \"SampleError\",\n \"message\": \"A sample error message.\",\n \"url\": \"https://openeo.example/docs/errors/SampleError\"\n}\n```\n\nSending `code` and `message` is REQUIRED. \n\n* A back-end MAY add a free-form `id` (unique identifier) to the error response to be able to log and track errors with further non-disclosable details.\n* The `code` is either one of the [standardized textual openEO error codes](errors.json) or a proprietary error code.\n* The `message` explains the reason the server is rejecting the request. For \"4xx\" error codes the message explains how the client needs to modify the request.\n\n By default the message MUST be sent in English language. Content Negotiation is used to localize the error messages: If an `Accept-Language` header is sent by the client and a translation is available, the message should be translated accordingly and the `Content-Language` header must be present in the response. See \"[How to localize your API](http://apiux.com/2013/04/25/how-to-localize-your-api/)\" for more information.\n* `url` is an OPTIONAL attribute and contains a link to a resource that is explaining the error and potential solutions in-depth.\n\n### Standardized status codes\n\nThe openEO API usually uses the following HTTP status codes for successful requests: \n\n- **200 OK**:\n Indicates a successful request **with** a response body being sent.\n- **201 Created**\n Indicates a successful request that successfully created a new resource. Sends a `Location` header to the newly created resource **without** a response body.\n- **202 Accepted**\n Indicates a successful request that successfully queued the creation of a new resource, but it has not been created yet. The response is sent **without** a response body.\n- **204 No Content**:\n Indicates a successful request **without** a response body being sent.\n\nThe openEO API has some commonly used HTTP status codes for failed requests: \n\n- **400 Bad Request**:\n The back-end responds with this error code whenever the error has its origin on client side and no other HTTP status code in the 400 range is suitable.\n\n- **401 Unauthorized**:\n The client did not provide any authentication details for a resource requiring authentication or the provided authentication details are not correct.\n\n- **403 Forbidden**:\n The client did provided correct authentication details, but the privileges/permissions of the provided credentials do not allow to request the resource.\n\n- **404 Not Found**:\n The resource specified by the path does not exist, i.e. one of the resources belonging to the specified identifiers are not available at the back-end.\n *Note:* Unsupported endpoints MAY also return HTTP status code 501.\n\n- **500 Internal Server Error**:\n The error has its origin on server side and no other status code in the 500 range is suitable.\n\n- **501 Not Implemented**:\n The requested endpoint is specified by the openEO API, but is not implemented (yet) by the back-end.\n *Note:* Unsupported endpoints MAY also return HTTP status code 404.\n\n\nIf a HTTP status code in the 400 range is returned, the client SHOULD NOT repeat the request without modifications. For HTTP status code in the 500 range, the client MAY repeat the same request later.\n\nAll HTTP status codes defined in RFC 7231 in the 400 and 500 ranges can be used as openEO error code in addition to the most used status codes mentioned here. Responding with openEO error codes 400 and 500 SHOULD be avoided in favor of any more specific standardized or proprietary openEO error code.\n\n## Temporal data\n\nDate, time, intervals and durations are formatted based on ISO 8601 or its profile [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) whenever there is an appropriate encoding available in the standard. All temporal data are specified based on the Gregorian calendar.\n\n# Authentication\n\nThe openEO API offers two forms of authentication by default:\n* OpenID Connect (recommended) at `GET /credentials/oidc`\n* Basic at `GET /credentials/basic`\n \nAfter authentication with any of the methods listed above, the tokens obtained during the authentication workflows can be sent to protected endpoints in subsequent requests.\n\nFurther authentication methods MAY be added by back-ends.\n\n\n\n**Note:** Although it is possible to request several public endpoints for capabilities and discovery that don't require authorization, it is RECOMMENDED that clients (re-)request the public endpoints that support Bearer authentication with the Bearer token once available to also retrieve any private data that is made available specifically for the authenticated user.\nThis may require that clients clear any cached data they retrieved from public endpoints before.\n\n# Cross-Origin Resource Sharing (CORS)\n\n> Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources [...] on a web page to be requested from another domain outside the domain from which the first resource was served. [...]\n> CORS defines a way in which a browser and server can interact to determine whether or not it is safe to allow the cross-origin request. It allows for more freedom and functionality than purely same-origin requests, but is more secure than simply allowing all cross-origin requests.\n\nSource: [https://en.wikipedia.org/wiki/Cross-origin_resource_sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)\n\nopenEO-based back-ends are usually hosted on a different domain / host than the client that is requesting data from the back-end. Therefore most requests to the back-end are blocked by all modern browsers. This leads to the problem that the JavaScript library and any browser-based application can't access back-ends. Therefore, all back-end providers SHOULD support CORS to enable browser-based applications to access back-ends. [CORS is a recommendation of the W3C organization](https://www.w3.org/TR/cors/). The following chapters will explain how back-end providers can implement CORS support.\n\n**Tip**: Most servers can send the required headers and the responses to the OPTIONS requests automatically for all endpoints. Otherwise you may also use a proxy server to add the headers and OPTIONS responses.\n\n## CORS headers\n\nThe following headers MUST be included with every response:\n\n| Name | Description | Example |\n| -------------------------------- | ------------------------------------------------------------ | ------- |\n| Access-Control-Allow-Origin | Allowed origin for the request, including protocol, host and port or `*` for all origins. It is RECOMMENDED to return the value `*` to allow requests from browser-based implementations such as the Web Editor. | `*` |\n| Access-Control-Expose-Headers | Some endpoints require to send additional HTTP response headers such as `OpenEO-Identifier` and `Location`. To make these headers available to browser-based clients, they MUST be white-listed with this CORS header. The following HTTP headers are white-listed by browsers and MUST NOT be included: `Cache-Control`, `Content-Language`, `Content-Length`, `Content-Type`, `Expires`, `Last-Modified` and `Pragma`. At least the following headers MUST be listed in this version of the openEO API: `Link`, `Location`, `OpenEO-Costs` and `OpenEO-Identifier`. | `Link, Location, OpenEO-Costs, OpenEO-Identifier` |\n\n\n\n### Example request and response\n\nRequest:\n\n```http\nPOST /api/v1/jobs HTTP/1.1\nHost: openeo.example\nOrigin: https://company.example:8080\nAuthorization: Bearer basic//ZXhhbXBsZTpleGFtcGxl\n```\n\nResponse:\n\n```http\nHTTP/1.1 201 Created\nAccess-Control-Allow-Origin: *\nAccess-Control-Expose-Headers: Location, OpenEO-Identifier, OpenEO-Costs, Link\nContent-Type: application/json\nLocation: https://openeo.example/api/v1/jobs/abc123\nOpenEO-Identifier: abc123\n```\n\n## OPTIONS method\n\nAll endpoints must respond to the `OPTIONS` HTTP method. This is a response for the preflight requests made by web browsers before sending the actual request (e.g. `POST /jobs`). It needs to respond with a status code of `204` and no response body.\n**In addition** to the HTTP headers shown in the table above, the following HTTP headers MUST be included with every response to an `OPTIONS` request:\n\n| Name | Description | Example |\n| -------------------------------- | ------------------------------------------------------------ | ------- |\n| Access-Control-Allow-Headers | Comma-separated list of HTTP headers allowed to be sent with the actual (non-preflight) request. MUST contain at least `Authorization` if any kind of authorization is implemented by the back-end. | `Authorization, Content-Type` |\n| Access-Control-Allow-Methods | Comma-separated list of HTTP methods allowed to be requested. Back-ends MUST list all implemented HTTP methods for the endpoint. | `OPTIONS, GET, POST, PATCH, PUT, DELETE` |\n| Content-Type | SHOULD return the content type delivered by the request that the permission is requested for. | `application/json` |\n\n### Example request and response\n\nRequest:\n\n```http\nOPTIONS /api/v1/jobs HTTP/1.1\nHost: openeo.example\nOrigin: https://company.example:8080\nAccess-Control-Request-Method: POST \nAccess-Control-Request-Headers: Authorization, Content-Type\n```\n\nNote that the `Access-Control-Request-*` headers are automatically attached to the requests by the browsers.\n\nResponse:\n\n```http\nHTTP/1.1 204 No Content\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: OPTIONS, GET, POST, PATCH, PUT, DELETE\nAccess-Control-Allow-Headers: Authorization, Content-Type\nAccess-Control-Expose-Headers: Location, OpenEO-Identifier, OpenEO-Costs, Link\nContent-Type: application/json\n```\n\n# Processes\n\nA **process** is an operation that performs a specific task on a set of parameters and returns a result. An example is computing a statistical operation, such as mean or median, on selected EO data. A process is similar to a function or method in programming languages. In openEO, processes are used to build a chain of processes ([process graph](#section/Processes/Process-Graphs)), which can be applied to EO data to derive your own findings from the data.\n\nA **predefined process** is a process provided by the *back-end*. There is a set of predefined processes by openEO to improve interoperability between back-ends.\nBack-ends SHOULD follow these specifications whenever possible. Not all processes need to be implemented by all back-ends. See the **[process reference](https://processes.openeo.org)** for predefined processes.\n\nA **user-defined process** is a process defined by the *user*. It can directly be part of another process graph or be stored as custom process on a back-end. Internally, it is a *process graph* with a variety of additional metadata.\n\nA **process graph** chains specific process calls from the set of predefined and user-defined processes together. A process graph itself can be stored as a (user-defined) process again. Similarly to scripts in the context of programming, process graphs organize and automate the execution of one or more processes that could alternatively be executed individually. In a process graph, processes need to be specific, i.e. concrete values or \"placeholders\" for input parameters need to be specified. These values can be scalars, arrays, objects, references to parameters or previous computations or other process graphs.\n\n## Defining Processes\n\nBack-ends and users MAY define new proprietary processes for their domain. \n\n**Back-end providers** MUST follow the schema for predefined processes as in [`GET /processes`](#operation/list-processes) to define new processes. This includes:\n\n* Choosing a intuitive process id, consisting of only letters (a-z), numbers and underscores. It MUST be unique across the predefined processes.\n* Defining the parameters and their exact (JSON) schemes.\n* Specifying the return value of a process also with a (JSON) schema.\n* Providing examples or compliance tests.\n* Trying to make the process universally usable so that other back-end providers or openEO can adopt it.\n\n**Users** MUST follow the schema for user-defined processes as in [`GET /process_graphs/{process_graph_id}`](#operation/describe-custom-process) to define new processes. This includes:\n\n* Choosing a intuitive name as process id, consisting of only letters (a-z), numbers and underscores. It MUST be unique per user across the user-defined processes.\n* Defining the algorithm as a process graph.\n* Optionally, specifying the additional metadata for processes.\n\nIf new process are potentially useful for other back-ends the openEO consortium is happily accepting [pull requests](https://github.com/Open-EO/openeo-processes/pulls) to include them in the list of predefined processes.\n\n### Schemas\n\nEach process parameter and the return values of a process define a schema that the value MUST comply to. The schemas are based on [JSON Schema draft-07](http://json-schema.org/).\n\nMultiple custom keywords have been defined:\n* `subtype` for more fine-grained data-types than JSON Schema supports.\n* `dimensions` to further define the dimension types required if the `subtype` is `datacube`.\n* `parameters` to specify the parameters of a process graph if the `subtype` is `process-graph`.\n* `returns` to describe the return value of a process graph if the `subtype` is `process-graph`.\n\n### Subtypes\n\nJSON Schema allows to specify only a small set of native data types (string, boolean, number, integer, array, object, null).\nTo support more fine grained data types, a custom [JSON Schema keyword](https://json-schema.org/draft-07/json-schema-core.html#rfc.section.6.4) has been defined: `subtype`.\nIt works similarly as the JSON Schema keyword [`format`](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.7)\nand standardizes a number of openEO related data types that extend the native data types, for example:\n`bounding-box` (object with at least `west`, `south`, `east` and `north` properties),\n`date-time` (string representation of date and time following RFC 3339),\n`datacube` (a datacube with dimensions), etc.\nThe subtypes should be re-used in process schema definitions whenever suitable.\n\nIf a general data type such as `string` or `number` is used in a schema, all subtypes with the same parent data type can be passed, too.\nClients should offer make passing subtypes as easy as passing a general data type.\nFor example, a parameter accepting strings must also allow passing a string with subtype `date` and thus clients should encourage this by also providing a date-picker.\n\nA list of predefined subtypes is available as JSON Schema in [openeo-processes](https://github.com/Open-EO/openeo-processes).\n\n## Process Graphs\n\nAs defined above, a **process graph** is a chain of processes with explicit values for their parameters.\nTechnically, a process graph is defined to be a graph of connected processes with exactly one node returning the final result:\n\n```\n := {\n \"\": ,\n ...\n}\n```\n\n`` is a unique key within the process graph that is used to reference (the return value of) this process in arguments of other processes. The identifier is unique only strictly within itself, excluding any parent and child process graphs. Process node identifiers are also strictly scoped and can not be referenced from child or parent process graphs. Circular references are not allowed.\n\nNote: We provide a non-binding [JSON Schema for basic process graph validation](assets/pg-schema.json).\n\n### Processes (Process Nodes)\n\nA single node in a process graph (i.e. a specific instance of a process) is defined as follows:\n\n```\n := {\n \"process_id\": ,\n \"namespace\": / null,\n \"description\": ,\n \"arguments\": ,\n \"result\": true / false\n}\n```\nA process node MUST always contain key-value-pairs named `process_id` and `arguments`. It MAY contain a `description`.\n\nOne of the nodes in a map of processes (the final one) MUST have the `result` flag set to `true`, all the other nodes can omit it as the default value is `false`. Having such a node is important as multiple end nodes are possible, but in most use cases it is important to exactly specify the return value to be used by other processes. Each child process graph must also specify a result node similar to the \"main\" process graph.\n\n`process_id` MUST be a valid process ID in the `namespace` given. Clients SHOULD warn the user if a user-defined process is added with the same identifier as one of the predefined process.\n\n### Arguments\n\nA process can have an arbitrary number of arguments. Their name and value are specified \nin the process specification as an object of key-value pairs:\n\n```\n := {\n \"\": \n}\n```\n\n**Notes:**\n- The specified data types are the native data types supported by JSON, except for `ResultReference`, `UserDefinedProcess` and `ParameterReference`.\n- Objects are not allowed to have keys with the following reserved names:\n\n * `from_node`, except for objects of type `ResultReference`\n * `process_graph`, except for objects of type `UserDefinedProcess`\n * `from_parameter`, except for objects of type `ParameterReference`\n\n- Arrays and objects can also contain a `ResultReference`, a `UserDefinedProcess` or a `ParameterReference`. So back-ends must *fully* traverse the process graphs, including all children.\n\n### Accessing results of other process nodes\n\nA value of type `` is an object with a key `from_node` and a `` as corresponding value:\n\n```\n := {\n \"from_node\": \"\"\n}\n```\n\nThis tells the back-end that the process expects the result (i.e. the return value) from another process node to be passed as argument.\nThe `` is strictly scoped and can only reference nodes from within the same process graph, not child or parent process graphs.\n\n### Child processes\n\nSome processes can run child processes, which is similar to the concept that other programming languages call\n[callbacks](https://en.wikipedia.org/wiki/Callback_(computer_programming)) or lambda functions.\nEach child process is simply a user-defined process again and can in theory be arbritarily complex.\n\nA very simple example would be to calculate the absolute value of each pixel in a data cube.\nThis can be achieved in openEO by using the `apply` process which gets the `absolute` process passed as child process.\nIn this example, the \"child\" processes consists of a single process `absolute`, but it can also be a more complex computation such as an NDVI or a prediciton based on a machine learning model.\n\n**Example**: \n\nA `` argument MUST at least consist of an object with a key `process_graph`.\nOptionally, it can also be described with the same additional properties available for predefined processes such as an id, parameters, return values etc.\nWhen embedded in a process graph, these additional properties of a user-defined process are usually not used, except for validation purposes.\n\n```\n := {\n \"process_graph\": ,\n ...\n}\n```\n\n### Accessing process parameters\n\nA \"parent\" process that works with a child process can make so called *process graph parameters*\navailable to the \"child\" logic.\nProcesses in the \"child\" process graph can access these parameters by passing a `ParameterReference` object as argument.\nIt is an object with key `from_parameter` specifying the name of the process graph parameter:\n\n```\n := {\n \"from_parameter\": \"\"\n}\n```\n\nThe parameter names made available for `` are defined and passed to the process graph by one of the parent entities.\nThe parent could be a process (such as `apply` or `reduce_dimension`) or something else that executes a process graph (a secondary web service for example).\nIf the parent is a process, the parameter are defined in the [`parameters` property](#section/Processes/Defining-Processes) of the corresponding JSON Schema.\n\nIn case of the example given above, the parameter `process` in the process [`apply`](https://processes.openeo.org/#apply) defines two process graph parameters: `x` (the value of each pixel that will be processed) and `context` (additional data passed through from the user).\nThe process `absolute` expects an argument with the same name `x`.\nThe process graph for the example would look as follows:\n\n```\n{\n \"process_id\": \"apply\",\n \"arguments\": {\n \"data\": {\"from_node\": \"loadcollection1\"}\n \"process\": {\n \"process_graph\": {\n \"abs1\": {\n \"process_id\": \"absolute\",\n \"arguments\": {\n \"x\": {\"from_parameter\": \"x\"}\n },\n \"result\": true\n }\n }\n }\n }\n}\n```\n\n`loadcollection1` would be a result from another process, which is not part of this example.\n\n**Important:** `` is less strictly scoped than ``.\n`` can be any parameter from the process graph or any of its parents.\n\nThe value for the parameter MUST be resolved as follows:\n1. In general the most specific parameter value is used. This means the parameter value is resolved starting from the current scope and then checking each parent for a suitable parameter value until a parameter values is found or the \"root\" process graph has been reached.\n2. In case a parameter value is not available, the most unspecific default value from the process graph parameter definitions are used. For example, if default values are available for the root process graph and all children, the default value from the root process graph is used.\n3. If no default values are available either, the error `ProcessParameterMissing` must be thrown.\n\n### Full example for an EVI computation\n\nDeriving minimum EVI (Enhanced Vegetation Index) measurements over pixel time series of Sentinel 2 imagery. The main process graph in blue, child process graphs in yellow:\n\n![Graph with processing instructions](assets/pg-evi-example.png)\n\nThe process graph for the algorithm: [pg-evi-example.json](assets/pg-evi-example.json)\n\n## Data Processing\n\nProcesses can run in three different ways:\n\n1. Results can be pre-computed by creating a ***batch job***. They are submitted to the back-end's processing system, but will remain inactive until explicitly put into the processing queue. They will run only once and store results after execution. Results can be downloaded. Batch jobs are typically time consuming and user interaction is not possible although log files are generated for them. This is the only mode that allows to get an estimate about time, volume and costs beforehand.\n\n2. A more dynamic way of processing and accessing data is to create a **secondary web service**. They allow web-based access using different protocols such as [OGC WMS](http://www.opengeospatial.org/standards/wms), [OGC WCS](http://www.opengeospatial.org/standards/wcs), [OGC API - Features](https://www.ogc.org/standards/ogcapi-features) or [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames). Some protocols such as the OGC WMS or XYZ tiles allow users to change the viewing extent or level of detail (zoom level). Therefore, computations often run *on demand* so that the requested data is calculated during the request. Back-ends should make sure to cache processed data to avoid additional/high costs and reduce waiting times for the user.\n\n3. Processes can also be executed **on-demand**\u00a0(i.e. synchronously). Results are delivered with the request itself and no job is created. Only lightweight computations, for example previews, should be executed using this approach as timeouts are to be expected for [long-polling HTTP requests](https://www.pubnub.com/blog/2014-12-01-http-long-polling/).\n\n### Validation\n\nProcess graph validation is a quite complex task. There's a [JSON schema](assets/pg-schema.json) for basic process graph validation. It checks the general structure of a process graph, but only checking against the schema is not fully validating a process graph. Note that this JSON Schema is probably good enough for a first version, but should be revised and improved for production. There are further steps to do:\n\n1. Validate whether there's exactly one `result: true` per process graph.\n2. Check whether the process names that are referenced in the field `process_id` are actually available in the corresponding `namespace`.\n3. Validate all arguments for each process against the JSON schemas that are specified in the corresponding process specifications.\n4. Check whether the values specified for `from_node` have a corresponding node in the same process graph.\n5. Validate whether the return value and the arguments requesting a return value with `from_node` are compatible.\n7. Check the content of arrays and objects. These could include parameter and result references (`from_node`, `from_parameter` etc.).\n\n\n### Execution\n\nTo process the process graph on the back-end you need to go through all nodes/processes in the list and set for each node to which node it passes data and from which it expects data. In another iteration the back-end can find all start nodes for processing by checking for zero dependencies.\n\nYou can now start and execute the start nodes (in parallel, if possible). Results can be passed to the nodes that were identified beforehand. For each node that depends on multiple inputs you need to check whether all dependencies have already finished and only execute once the last dependency is ready.\n\nPlease be aware that the result node (`result` set to `true`) is not necessarily the last node that is executed. The author of the process graph may choose to set a non-end node to the result node!", - "contact": { - "name": "openEO Consortium", - "url": "https://openeo.org", - "email": "openeo.psc@uni-muenster.de" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - } + "title": "openEO API", + "version": "1.2.0", + "description": "The openEO API specification for interoperable cloud-based processing of large Earth observation datasets.\n\n**Conformance class:** `https://api.openeo.org/1.2.0`\n\n# API Principles\n\n## Language\n\nIn the specification the key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.html) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174.html).\n\n## Casing\n\nUnless otherwise stated the API works **case sensitive**.\n\nAll names SHOULD be written in snake case, i.e. words are separated with one underscore character (`_`) and no spaces, with all letters lower-cased. Example: `hello_world`. This applies particularly to endpoints and JSON property names. HTTP header fields are generally case-insensitive according to [RFC 7230](https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2) and in the specification we follow their respective casing conventions, e.g. `Content-Type` or `OpenEO-Costs`, for better readability and consistency.\n\n## HTTP / REST\n\nThis uses [HTTP REST](https://en.wikipedia.org/wiki/Representational_state_transfer) [Level 2](https://martinfowler.com/articles/richardsonMaturityModel.html#level2) for communication between client and back-end server.\n\nPublic APIs MUST be available via HTTPS only. \n\nEndpoints are made use meaningful HTTP verbs (e.g. GET, POST, PUT, PATCH, DELETE) whenever technically possible. If there is a need to transfer big chunks of data for a GET requests to the back-end, POST requests MAY be used as a replacement as they support to send data via request body. Unless otherwise stated, PATCH requests are only defined to work on direct (first-level) children of the full JSON object. Therefore, changing a property on a deeper level of the full JSON object always requires to send the whole JSON object defined by the first-level property.\n\nNaming of endpoints follow the REST principles. Therefore, endpoints are centered around resources. Resource identifiers MUST be named with a noun in plural form except for single actions that can not be modelled with the regular HTTP verbs. Single actions MUST be single endpoints with a single HTTP verb (POST is RECOMMENDED) and no other endpoints beneath it.\n\nThe openEO API makes use of [HTTP Content Negotiation](https://www.rfc-editor.org/rfc/rfc9110.html#name-content-negotiation),\nincluding, but not limited to, the request headers `Accept`, `Accept-Charset` and `Accept-Language`.\n\n### JSON\n\nThe API uses JSON for request and response bodies whenever feasible. Services use JSON as the default encoding. Other encodings can be requested using HTTP Content Negotiation ([`Accept` header](https://www.rfc-editor.org/rfc/rfc9110.html#name-accept)). Clients and servers MUST NOT rely on the order in which properties appear in JSON. To keep the response size small, lists of resources (e.g. the list of batch jobs) usually should not include nested JSON objects, if this information can be requested from the individual resource endpoints (e.g. the metadata for a single batch job).\n\n### Charset\n\nServices use [UTF-8](https://en.wikipedia.org/wiki/UTF-8) as the default charset if not negotiated otherwise with HTTP Content Negotiation ([`Accept-Charset` header](https://www.rfc-editor.org/rfc/rfc9110.html#name-accept-charset)).\n\n## Web Linking\n\nThe API is designed in a way that to most entities (e.g. collections and processes) a set of links can be added. These can be alternate representations, e.g. data discovery via OGC WCS or OGC CSW, references to a license, references to actual raw data for downloading, detailed information about pre-processing and more. Clients should allow users to follow the links.\n\nWhenever links are utilized in the API, the description explains which relation (`rel` property) types are commonly used.\nA [list of standardized link relations types is provided by IANA](https://www.iana.org/assignments/link-relations/link-relations.xhtml) and the API tries to align whenever feasible.\n\nSome very common relation types - usually not mentioned explicitly in the description of `links` fields - are:\n\n1. `self`: which allows link to the location that the resource can be (permanently) found online.This is particularly useful when the data is data is made available offline, so that the downstream user knows where the data has come from.\n\n2. `alternate`: An alternative representation of the resource, may it be another metadata standard the data is available in or simply a human-readable version in HTML or PDF.\n\n3. `about`: A resource that is related or further explains the resource, e.g. a user guide.\n\n4. `canonical`: This relation type usually points to a publicly accessible and more long-lived URL for a resource that otherwise often requires (Bearer) authentication with a short-lived token.\nThis way the the exposed resources can be used by non-openEO clients without additional authentication steps.\nFor example, a shared user-defined process or batch job results could be exposed via a canonical link.\nIf a URL should be publicly available to everyone, it can simply a user-specific URL, e.g. `https://openeo.example/processes/john_doe/ndvi`.\nFor resources that should only be accessible to a certain group of user, a signed URL could be given, e.g. `https://openeo.example/processes/81zjh1tc2pt52gbx/ndvi`.\n\nGenerally, it is RECOMMENDED to add descriptive titles (propertty `title`) and media type information (propertty `type`) for a better user experience.\n\n## Error Handling\n\nThe success of requests MUST be indicated using [HTTP status codes](https://www.rfc-editor.org/rfc/rfc7231.html#section-6) according to [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html).\n\nIf the API responds with a status code between 100 and 399 the back-end indicates that the request has been handled successfully.\n\nIn general an error is communicated with a status code between 400 and 599. Client errors are defined as a client passing invalid data to the service and the service *correctly* rejecting that data. Examples include invalid credentials, incorrect parameters, unknown versions, or similar. These are generally \"4xx\" HTTP error codes and are the result of a client passing incorrect or invalid data. Client errors do *not* contribute to overall API availability. \n\nServer errors are defined as the server failing to correctly return in response to a valid client request. These are generally \"5xx\" HTTP error codes. Server errors *do* contribute to the overall API availability. Calls that fail due to rate limiting or quota failures MUST NOT count as server errors. \n\n### JSON error object\n\nA JSON error object SHOULD be sent with all responses that have a status code between 400 and 599.\n\n``` json\n{\n \"id\": \"936DA01F-9ABD-4D9D-80C7-02AF85C822A8\",\n \"code\": \"SampleError\",\n \"message\": \"A sample error message.\",\n \"url\": \"https://openeo.example/docs/errors/SampleError\"\n}\n```\n\nSending `code` and `message` is REQUIRED. \n\n* A back-end MAY add a free-form `id` (unique identifier) to the error response to be able to log and track errors with further non-disclosable details.\n* The `code` is either one of the [standardized textual openEO error codes](errors.json) or a proprietary error code.\n* The `message` explains the reason the server is rejecting the request. For \"4xx\" error codes the message explains how the client needs to modify the request.\n\n By default the message MUST be sent in English language. Content Negotiation is used to localize the error messages: If an `Accept-Language` header is sent by the client and a translation is available, the message should be translated accordingly and the `Content-Language` header must be present in the response. See \"[How to localize your API](http://apiux.com/2013/04/25/how-to-localize-your-api/)\" for more information.\n* `url` is an OPTIONAL attribute and contains a link to a resource that is explaining the error and potential solutions in-depth.\n\n### Standardized status codes\n\nThe openEO API usually uses the following HTTP status codes for successful requests: \n\n- **200 OK**:\n Indicates a successful request **with** a response body being sent.\n- **201 Created**\n Indicates a successful request that successfully created a new resource. Sends a `Location` header to the newly created resource **without** a response body.\n- **202 Accepted**\n Indicates a successful request that successfully queued the creation of a new resource, but it has not been created yet. The response is sent **without** a response body.\n- **204 No Content**:\n Indicates a successful request **without** a response body being sent.\n\nThe openEO API has some commonly used HTTP status codes for failed requests: \n\n- **400 Bad Request**:\n The back-end responds with this error code whenever the error has its origin on client side and no other HTTP status code in the 400 range is suitable.\n\n- **401 Unauthorized**:\n The client did not provide any authentication details for a resource requiring authentication or the provided authentication details are not correct.\n\n- **403 Forbidden**:\n The client did provided correct authentication details, but the privileges/permissions of the provided credentials do not allow to request the resource.\n\n- **404 Not Found**:\n The resource specified by the path does not exist, i.e. one of the resources belonging to the specified identifiers are not available at the back-end.\n *Note:* Unsupported endpoints MAY also return HTTP status code 501.\n\n- **500 Internal Server Error**:\n The error has its origin on server side and no other status code in the 500 range is suitable.\n\n- **501 Not Implemented**:\n The requested endpoint is specified by the openEO API, but is not implemented (yet) by the back-end.\n *Note:* Unsupported endpoints MAY also return HTTP status code 404.\n\n\nIf a HTTP status code in the 400 range is returned, the client SHOULD NOT repeat the request without modifications. For HTTP status code in the 500 range, the client MAY repeat the same request later.\n\nAll HTTP status codes defined in RFC 7231 in the 400 and 500 ranges can be used as openEO error code in addition to the most used status codes mentioned here. Responding with openEO error codes 400 and 500 SHOULD be avoided in favor of any more specific standardized or proprietary openEO error code.\n\n## Temporal data\n\nDate, time, intervals and durations are formatted based on ISO 8601 or its profile [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) whenever there is an appropriate encoding available in the standard. All temporal data are specified based on the Gregorian calendar.\n\n# Authentication\n\nThe openEO API offers two forms of authentication by default:\n* OpenID Connect (recommended) at `GET /credentials/oidc`\n* Basic at `GET /credentials/basic`\n \nAfter authentication with any of the methods listed above, the tokens obtained during the authentication workflows can be sent to protected endpoints in subsequent requests.\n\nFurther authentication methods MAY be added by back-ends.\n\n\n\n**Note:** Although it is possible to request several public endpoints for capabilities and discovery that don't require authorization, it is RECOMMENDED that clients (re-)request the public endpoints that support Bearer authentication with the Bearer token once available to also retrieve any private data that is made available specifically for the authenticated user.\nThis may require that clients clear any cached data they retrieved from public endpoints before.\n\n# Cross-Origin Resource Sharing (CORS)\n\n> Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources [...] on a web page to be requested from another domain outside the domain from which the first resource was served. [...]\n> CORS defines a way in which a browser and server can interact to determine whether or not it is safe to allow the cross-origin request. It allows for more freedom and functionality than purely same-origin requests, but is more secure than simply allowing all cross-origin requests.\n\nSource: [https://en.wikipedia.org/wiki/Cross-origin_resource_sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)\n\nopenEO-based back-ends are usually hosted on a different domain / host than the client that is requesting data from the back-end. Therefore most requests to the back-end are blocked by all modern browsers. This leads to the problem that the JavaScript library and any browser-based application can't access back-ends. Therefore, all back-end providers SHOULD support CORS to enable browser-based applications to access back-ends. [CORS is a recommendation of the W3C organization](https://www.w3.org/TR/cors/). The following chapters will explain how back-end providers can implement CORS support.\n\n**Tip**: Most servers can send the required headers and the responses to the OPTIONS requests automatically for all endpoints. Otherwise you may also use a proxy server to add the headers and OPTIONS responses.\n\n## CORS headers\n\nThe following headers MUST be included with every response:\n\n| Name | Description | Example |\n| -------------------------------- | ------------------------------------------------------------ | ------- |\n| Access-Control-Allow-Origin | Allowed origin for the request, including protocol, host and port or `*` for all origins. It is RECOMMENDED to return the value `*` to allow requests from browser-based implementations such as the Web Editor. | `*` |\n| Access-Control-Expose-Headers | Some endpoints require to send additional HTTP response headers such as `OpenEO-Identifier` and `Location`. To make these headers available to browser-based clients, they MUST be white-listed with this CORS header. The following HTTP headers are white-listed by browsers and MUST NOT be included: `Cache-Control`, `Content-Language`, `Content-Length`, `Content-Type`, `Expires`, `Last-Modified` and `Pragma`. At least the following headers MUST be listed in this version of the openEO API: `Link`, `Location`, `OpenEO-Costs` and `OpenEO-Identifier`. | `Link, Location, OpenEO-Costs, OpenEO-Identifier` |\n\n\n\n### Example request and response\n\nRequest:\n\n```http\nPOST /api/v1/jobs HTTP/1.1\nHost: openeo.example\nOrigin: https://company.example:8080\nAuthorization: Bearer basic//ZXhhbXBsZTpleGFtcGxl\n```\n\nResponse:\n\n```http\nHTTP/1.1 201 Created\nAccess-Control-Allow-Origin: *\nAccess-Control-Expose-Headers: Location, OpenEO-Identifier, OpenEO-Costs, Link\nContent-Type: application/json\nLocation: https://openeo.example/api/v1/jobs/abc123\nOpenEO-Identifier: abc123\n```\n\n## OPTIONS method\n\nAll endpoints must respond to the `OPTIONS` HTTP method. This is a response for the preflight requests made by web browsers before sending the actual request (e.g. `POST /jobs`). It needs to respond with a status code of `204` and no response body.\n**In addition** to the HTTP headers shown in the table above, the following HTTP headers MUST be included with every response to an `OPTIONS` request:\n\n| Name | Description | Example |\n| -------------------------------- | ------------------------------------------------------------ | ------- |\n| Access-Control-Allow-Headers | Comma-separated list of HTTP headers allowed to be sent with the actual (non-preflight) request. MUST contain at least `Authorization` if any kind of authorization is implemented by the back-end. | `Authorization, Content-Type` |\n| Access-Control-Allow-Methods | Comma-separated list of HTTP methods allowed to be requested. Back-ends MUST list all implemented HTTP methods for the endpoint. | `OPTIONS, GET, POST, PATCH, PUT, DELETE` |\n| Content-Type | SHOULD return the content type delivered by the request that the permission is requested for. | `application/json` |\n\n### Example request and response\n\nRequest:\n\n```http\nOPTIONS /api/v1/jobs HTTP/1.1\nHost: openeo.example\nOrigin: https://company.example:8080\nAccess-Control-Request-Method: POST \nAccess-Control-Request-Headers: Authorization, Content-Type\n```\n\nNote that the `Access-Control-Request-*` headers are automatically attached to the requests by the browsers.\n\nResponse:\n\n```http\nHTTP/1.1 204 No Content\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: OPTIONS, GET, POST, PATCH, PUT, DELETE\nAccess-Control-Allow-Headers: Authorization, Content-Type\nAccess-Control-Expose-Headers: Location, OpenEO-Identifier, OpenEO-Costs, Link\nContent-Type: application/json\n```\n\n# Processes\n\nA **process** is an operation that performs a specific task on a set of parameters and returns a result. An example is computing a statistical operation, such as mean or median, on selected EO data. A process is similar to a function or method in programming languages. In openEO, processes are used to build a chain of processes ([process graph](#section/Processes/Process-Graphs)), which can be applied to EO data to derive your own findings from the data.\n\nA **predefined process** is a process provided by the *back-end*. There is a set of predefined processes by openEO to improve interoperability between back-ends.\nBack-ends SHOULD follow these specifications whenever possible. Not all processes need to be implemented by all back-ends. See the **[process reference](https://processes.openeo.org)** for predefined processes.\n\nA **user-defined process** is a process defined by the *user*. It can directly be part of another process graph or be stored as custom process on a back-end. Internally, it is a *process graph* with a variety of additional metadata.\n\nA **process graph** chains specific process calls from the set of predefined and user-defined processes together. A process graph itself can be stored as a (user-defined) process again. Similarly to scripts in the context of programming, process graphs organize and automate the execution of one or more processes that could alternatively be executed individually. In a process graph, processes need to be specific, i.e. concrete values or \"placeholders\" for input parameters need to be specified. These values can be scalars, arrays, objects, references to parameters or previous computations or other process graphs.\n\n## Defining Processes\n\nBack-ends and users MAY define new proprietary processes for their domain. \n\n**Back-end providers** MUST follow the schema for predefined processes as in [`GET /processes`](#operation/list-processes) to define new processes. This includes:\n\n* Choosing a intuitive process id, consisting of only letters (a-z), numbers and underscores. It MUST be unique across the predefined processes.\n* Defining the parameters and their exact (JSON) schemes.\n* Specifying the return value of a process also with a (JSON) schema.\n* Providing examples or compliance tests.\n* Trying to make the process universally usable so that other back-end providers or openEO can adopt it.\n\n**Users** MUST follow the schema for user-defined processes as in [`GET /process_graphs/{process_graph_id}`](#operation/describe-custom-process) to define new processes. This includes:\n\n* Choosing a intuitive name as process id, consisting of only letters (a-z), numbers and underscores. It MUST be unique per user across the user-defined processes.\n* Defining the algorithm as a process graph.\n* Optionally, specifying the additional metadata for processes.\n\nIf new process are potentially useful for other back-ends the openEO consortium is happily accepting [pull requests](https://github.com/Open-EO/openeo-processes/pulls) to include them in the list of predefined processes.\n\n### Schemas\n\nEach process parameter and the return values of a process define a schema that the value MUST comply to. The schemas are based on [JSON Schema draft-07](http://json-schema.org/).\n\nMultiple custom keywords have been defined:\n* `subtype` for more fine-grained data-types than JSON Schema supports.\n* `dimensions` to further define the dimension types required if the `subtype` is `datacube`.\n* `parameters` to specify the parameters of a process graph if the `subtype` is `process-graph`.\n* `returns` to describe the return value of a process graph if the `subtype` is `process-graph`.\n\n### Subtypes\n\nJSON Schema allows to specify only a small set of native data types (string, boolean, number, integer, array, object, null).\nTo support more fine grained data types, a custom [JSON Schema keyword](https://json-schema.org/draft-07/json-schema-core.html#rfc.section.6.4) has been defined: `subtype`.\nIt works similarly as the JSON Schema keyword [`format`](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.7)\nand standardizes a number of openEO related data types that extend the native data types, for example:\n`bounding-box` (object with at least `west`, `south`, `east` and `north` properties),\n`date-time` (string representation of date and time following RFC 3339),\n`datacube` (a datacube with dimensions), etc.\nThe subtypes should be re-used in process schema definitions whenever suitable.\n\nIf a general data type such as `string` or `number` is used in a schema, all subtypes with the same parent data type can be passed, too.\nClients should offer make passing subtypes as easy as passing a general data type.\nFor example, a parameter accepting strings must also allow passing a string with subtype `date` and thus clients should encourage this by also providing a date-picker.\n\nA list of predefined subtypes is available as JSON Schema in [openeo-processes](https://github.com/Open-EO/openeo-processes).\n\n## Process Graphs\n\nAs defined above, a **process graph** is a chain of processes with explicit values for their parameters.\nTechnically, a process graph is defined to be a graph of connected processes with exactly one node returning the final result:\n\n```\n := {\n \"\": ,\n ...\n}\n```\n\n`` is a unique key within the process graph that is used to reference (the return value of) this process in arguments of other processes. The identifier is unique only strictly within itself, excluding any parent and child process graphs. Process node identifiers are also strictly scoped and can not be referenced from child or parent process graphs. Circular references are not allowed.\n\nNote: We provide a non-binding [JSON Schema for basic process graph validation](assets/pg-schema.json).\n\n### Processes (Process Nodes)\n\nA single node in a process graph (i.e. a specific instance of a process) is defined as follows:\n\n```\n := {\n \"process_id\": ,\n \"namespace\": / null,\n \"description\": ,\n \"arguments\": ,\n \"result\": true / false\n}\n```\nA process node MUST always contain key-value-pairs named `process_id` and `arguments`. It MAY contain a `description`.\n\nOne of the nodes in a map of processes (the final one) MUST have the `result` flag set to `true`, all the other nodes can omit it as the default value is `false`. Having such a node is important as multiple end nodes are possible, but in most use cases it is important to exactly specify the return value to be used by other processes. Each child process graph must also specify a result node similar to the \"main\" process graph.\n\n`process_id` MUST be a valid process ID in the `namespace` given. Clients SHOULD warn the user if a user-defined process is added with the same identifier as one of the predefined process.\n\n### Arguments\n\nA process can have an arbitrary number of arguments. Their name and value are specified \nin the process specification as an object of key-value pairs:\n\n```\n := {\n \"\": \n}\n```\n\n**Notes:**\n- The specified data types are the native data types supported by JSON, except for `ResultReference`, `UserDefinedProcess` and `ParameterReference`.\n- Objects are not allowed to have keys with the following reserved names:\n\n * `from_node`, except for objects of type `ResultReference`\n * `process_graph`, except for objects of type `UserDefinedProcess`\n * `from_parameter`, except for objects of type `ParameterReference`\n\n- Arrays and objects can also contain a `ResultReference`, a `UserDefinedProcess` or a `ParameterReference`. So back-ends must *fully* traverse the process graphs, including all children.\n\n### Accessing results of other process nodes\n\nA value of type `` is an object with a key `from_node` and a `` as corresponding value:\n\n```\n := {\n \"from_node\": \"\"\n}\n```\n\nThis tells the back-end that the process expects the result (i.e. the return value) from another process node to be passed as argument.\nThe `` is strictly scoped and can only reference nodes from within the same process graph, not child or parent process graphs.\n\n### Child processes\n\nSome processes can run child processes, which is similar to the concept that other programming languages call\n[callbacks](https://en.wikipedia.org/wiki/Callback_(computer_programming)) or lambda functions.\nEach child process is simply a user-defined process again and can in theory be arbritarily complex.\n\nA very simple example would be to calculate the absolute value of each pixel in a data cube.\nThis can be achieved in openEO by using the `apply` process which gets the `absolute` process passed as child process.\nIn this example, the \"child\" processes consists of a single process `absolute`, but it can also be a more complex computation such as an NDVI or a prediciton based on a machine learning model.\n\n**Example**: \n\nA `` argument MUST at least consist of an object with a key `process_graph`.\nOptionally, it can also be described with the same additional properties available for predefined processes such as an id, parameters, return values etc.\nWhen embedded in a process graph, these additional properties of a user-defined process are usually not used, except for validation purposes.\n\n```\n := {\n \"process_graph\": ,\n ...\n}\n```\n\n### Accessing process parameters\n\nA \"parent\" process that works with a child process can make so called *process graph parameters*\navailable to the \"child\" logic.\nProcesses in the \"child\" process graph can access these parameters by passing a `ParameterReference` object as argument.\nIt is an object with key `from_parameter` specifying the name of the process graph parameter:\n\n```\n := {\n \"from_parameter\": \"\"\n}\n```\n\nThe parameter names made available for `` are defined and passed to the process graph by one of the parent entities.\nThe parent could be a process (such as `apply` or `reduce_dimension`) or something else that executes a process graph (a secondary web service for example).\nIf the parent is a process, the parameter are defined in the [`parameters` property](#section/Processes/Defining-Processes) of the corresponding JSON Schema.\n\nIn case of the example given above, the parameter `process` in the process [`apply`](https://processes.openeo.org/#apply) defines two process graph parameters: `x` (the value of each pixel that will be processed) and `context` (additional data passed through from the user).\nThe process `absolute` expects an argument with the same name `x`.\nThe process graph for the example would look as follows:\n\n```\n{\n \"process_id\": \"apply\",\n \"arguments\": {\n \"data\": {\"from_node\": \"loadcollection1\"}\n \"process\": {\n \"process_graph\": {\n \"abs1\": {\n \"process_id\": \"absolute\",\n \"arguments\": {\n \"x\": {\"from_parameter\": \"x\"}\n },\n \"result\": true\n }\n }\n }\n }\n}\n```\n\n`loadcollection1` would be a result from another process, which is not part of this example.\n\n**Important:** `` is less strictly scoped than ``.\n`` can be any parameter from the process graph or any of its parents.\n\nThe value for the parameter MUST be resolved as follows:\n1. In general the most specific parameter value is used. This means the parameter value is resolved starting from the current scope and then checking each parent for a suitable parameter value until a parameter values is found or the \"root\" process graph has been reached.\n2. In case a parameter value is not available, the most unspecific default value from the process graph parameter definitions are used. For example, if default values are available for the root process graph and all children, the default value from the root process graph is used.\n3. If no default values are available either, the error `ProcessParameterMissing` must be thrown.\n\n### Full example for an EVI computation\n\nDeriving minimum EVI (Enhanced Vegetation Index) measurements over pixel time series of Sentinel 2 imagery. The main process graph in blue, child process graphs in yellow:\n\n![Graph with processing instructions](assets/pg-evi-example.png)\n\nThe process graph for the algorithm: [pg-evi-example.json](assets/pg-evi-example.json)\n\n## Data Processing\n\nProcesses can run in three different ways:\n\n1. Results can be pre-computed by creating a ***batch job***. They are submitted to the back-end's processing system, but will remain inactive until explicitly put into the processing queue. They will run only once and store results after execution. Results can be downloaded. Batch jobs are typically time consuming and user interaction is not possible although log files are generated for them. This is the only mode that allows to get an estimate about time, volume and costs beforehand.\n\n2. A more dynamic way of processing and accessing data is to create a **secondary web service**. They allow web-based access using different protocols such as [OGC WMS](http://www.opengeospatial.org/standards/wms), [OGC WCS](http://www.opengeospatial.org/standards/wcs), [OGC API - Features](https://www.ogc.org/standards/ogcapi-features) or [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames). Some protocols such as the OGC WMS or XYZ tiles allow users to change the viewing extent or level of detail (zoom level). Therefore, computations often run *on demand* so that the requested data is calculated during the request. Back-ends should make sure to cache processed data to avoid additional/high costs and reduce waiting times for the user.\n\n3. Processes can also be executed **on-demand** (i.e. synchronously). Results are delivered with the request itself and no job is created. Only lightweight computations, for example previews, should be executed using this approach as timeouts are to be expected for [long-polling HTTP requests](https://www.pubnub.com/blog/2014-12-01-http-long-polling/).\n\n### Validation\n\nProcess graph validation is a quite complex task. There's a [JSON schema](assets/pg-schema.json) for basic process graph validation. It checks the general structure of a process graph, but only checking against the schema is not fully validating a process graph. Note that this JSON Schema is probably good enough for a first version, but should be revised and improved for production. There are further steps to do:\n\n1. Validate whether there's exactly one `result: true` per process graph.\n2. Check whether the process names that are referenced in the field `process_id` are actually available in the corresponding `namespace`.\n3. Validate all arguments for each process against the JSON schemas that are specified in the corresponding process specifications.\n4. Check whether the values specified for `from_node` have a corresponding node in the same process graph.\n5. Validate whether the return value and the arguments requesting a return value with `from_node` are compatible.\n7. Check the content of arrays and objects. These could include parameter and result references (`from_node`, `from_parameter` etc.).\n\n\n### Execution\n\nTo process the process graph on the back-end you need to go through all nodes/processes in the list and set for each node to which node it passes data and from which it expects data. In another iteration the back-end can find all start nodes for processing by checking for zero dependencies.\n\nYou can now start and execute the start nodes (in parallel, if possible). Results can be passed to the nodes that were identified beforehand. For each node that depends on multiple inputs you need to check whether all dependencies have already finished and only execute once the last dependency is ready.\n\nPlease be aware that the result node (`result` set to `true`) is not necessarily the last node that is executed. The author of the process graph may choose to set a non-end node to the result node!", + "contact": { + "name": "openEO Consortium", + "url": "https://openeo.org", + "email": "openeo.psc@uni-muenster.de" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } }, "externalDocs": { - "description": "openEO Documentation", - "url": "https://openeo.org/documentation/1.0/" + "description": "openEO Documentation", + "url": "https://openeo.org/documentation/1.0/" }, "tags": [ - { - "name": "Capabilities", - "description": "General information about the API implementation and other supported capabilities at the back-end." - }, - { - "name": "Account Management", - "description": "The following endpoints handle user profiles, accounting and authentication. See also [Authentication](#section/Authentication). In general, the openEO API only defines a minimum subset of user management and accounting functionality. It allows to\n\n* [authenticate and authorize](http://www.differencebetween.net/technology/difference-between-authentication-and-authorization/) a user, which may include [user registration with OpenID Connect](http://openid.net/specs/openid-connect-registration-1_0.html),\n* handle storage space limits (disk quota),\n* manage billing, which includes to\n * query the credit a user has available,\n * estimate costs for certain operations (data processing and downloading),\n * get information about produced costs,\n * limit costs of certain operations.\n\nTherefore, the API leaves some aspects open that have to be handled by the back-ends separately, including \n\n* credentials recovery, e.g. retrieving a forgotten password\n* user data management, e.g. changing the users payment details or email address\n* payments, i.e. topping up credits for pre-paid services or paying for post-paid services\n* other accounting related tasks, e.g. creating invoices,\n* user registration (except for [user registration with OpenID Connect](http://openid.net/specs/openid-connect-registration-1_0.html))." - }, - { - "name": "EO Data Discovery", - "description": "These endpoints allow to list the collections that are available at the back-end and can be used as data cubes for data processing.\n\n## STAC\n\nFor data discovery of Earth Observation Collections at the back-ends, openEO strives for compatibility with the specifications [SpatioTemporal Asset Catalog (STAC)](https://stacspec.org/) and [OGC API - Features - Part 1: Core](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html) as far as possible. Implementing the data discovery endpoints of openEO also produced valid STAC API 1.0 and OGC API - Features 1.0 responses, including ([partial](#provide-data-for-download)) compatibility with their APIs. \n\nThe data discovery endpoints `GET /collections` and `GET /collections/{collection_id}` are compatible with OGC API - Features and STAC. Both specifications define additional endpoints that need to be implemented to be fully compatible. The additional endpoints can easily be integrated into an openEO API implementation. A rough list of actions for compatibility is available below, but please refer to their specifications to find out the full details.\n\n**Important:** [STAC specification](https://github.com/radiantearth/stac-spec) and [STAC API](https://github.com/radiantearth/stac-api-spec) are different specifications and have different version numbers after version 0.9.0.\nThe openEO API implements STAC API versions >= 0.9.0 (preferrably [STAC API version 1.0.0](https://github.com/radiantearth/stac-api-spec/blob/v1.0.0/README.md), but [0.9.0](https://github.com/radiantearth/stac-spec/blob/v0.9.0/api-spec/README.md) is allowed for backward compatibility), which allows to serve all STAC specification versions in the range of 0.9.x and 1.x.x (see the `stac_version` property).\n\n### Content Extensions\n\nSTAC has several [extensions](https://stac-extensions.github.io) that can be used to better describe your data. Clients and server are not required to implement all of them, so be aware that some clients may not be able to read all your metadata.\n\nSome commonly used extensions that are relevant for datasets exposed through the openEO API are:\n\n- Data Cube extension (part of the openEO API)\n- [EO (Electro-Optical) extension](https://github.com/stac-extensions/eo)\n- [Processing extension](https://github.com/stac-extensions/processing)\n- [Raster extension](https://github.com/stac-extensions/raster)\n- [SAR extension](https://github.com/stac-extensions/sar)\n- [Satellite extension](https://github.com/stac-extensions/sat)\n- [Scientific Citation extension](https://github.com/stac-extensions/scientific)\n\n### Provide data for download\n\nIf you'd like to provide your data for download in addition to offering the cloud processing service, you can implement the full STAC API. Therefore you can implement the endpoints `GET /collections/{collection_id}/items` and `GET /collections/{collection_id}/items/{feature_id}` to support retrieval of individual items. To benefit from the STAC ecosystem and allow searching for items you can also implement `POST /search` and `GET /search`. Further information can be found in the [STAC API repository](https://github.com/radiantearth/stac-spec/tree/v0.9.0/api-spec).\n\n### API Extensions\n\nSTAC API has several [extensions](https://stac-api-extensions.github.io) that can be implemented on top of the openEO API to enrich the API functionality, e.g. for searching." - }, - { - "name": "Process Discovery", - "description": "These endpoints allow to list the predefined processes that are available at the back-end. To list user-defined processes see '[User-Defined Processes](#tag/User-Defined-Processes)'." - }, - { - "name": "User-Defined Processes", - "description": "These endpoints allow to store and manage user-defined processes with their process graphs at the back-end." - }, - { - "name": "Data Processing", - "description": "Organizes and manages data processing on the back-end, either as synchronous on-demand computation or batch jobs." - }, - { - "name": "Batch Jobs", - "description": "Management of batch processing tasks (jobs) and their results." - }, - { - "name": "Secondary Services", - "description": "On-demand access to data using other web service protocols." - }, - { - "name": "File Storage", - "description": "Management of user-uploaded assets and processed data." - } + { + "name": "Capabilities", + "description": "General information about the API implementation and other supported capabilities at the back-end." + }, + { + "name": "Account Management", + "description": "The following endpoints handle user profiles, accounting and authentication. See also [Authentication](#section/Authentication). In general, the openEO API only defines a minimum subset of user management and accounting functionality. It allows to\n\n* [authenticate and authorize](http://www.differencebetween.net/technology/difference-between-authentication-and-authorization/) a user, which may include [user registration with OpenID Connect](http://openid.net/specs/openid-connect-registration-1_0.html),\n* handle storage space limits (disk quota),\n* manage billing, which includes to\n * query the credit a user has available,\n * estimate costs for certain operations (data processing and downloading),\n * get information about produced costs,\n * limit costs of certain operations.\n\nTherefore, the API leaves some aspects open that have to be handled by the back-ends separately, including \n\n* credentials recovery, e.g. retrieving a forgotten password\n* user data management, e.g. changing the users payment details or email address\n* payments, i.e. topping up credits for pre-paid services or paying for post-paid services\n* other accounting related tasks, e.g. creating invoices,\n* user registration (except for [user registration with OpenID Connect](http://openid.net/specs/openid-connect-registration-1_0.html))." + }, + { + "name": "EO Data Discovery", + "description": "These endpoints allow to list the collections that are available at the back-end and can be used as data cubes for data processing.\n\n## STAC\n\nFor data discovery of Earth Observation Collections at the back-ends, openEO strives for compatibility with the specifications [SpatioTemporal Asset Catalog (STAC)](https://stacspec.org/) and [OGC API - Features - Part 1: Core](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html) as far as possible. Implementing the data discovery endpoints of openEO also produced valid STAC API 1.0 and OGC API - Features 1.0 responses, including ([partial](#provide-data-for-download)) compatibility with their APIs. \n\nThe data discovery endpoints `GET /collections` and `GET /collections/{collection_id}` are compatible with OGC API - Features and STAC. Both specifications define additional endpoints that need to be implemented to be fully compatible. The additional endpoints can easily be integrated into an openEO API implementation. A rough list of actions for compatibility is available below, but please refer to their specifications to find out the full details.\n\n**Important:** [STAC specification](https://github.com/radiantearth/stac-spec) and [STAC API](https://github.com/radiantearth/stac-api-spec) are different specifications and have different version numbers after version 0.9.0.\nThe openEO API implements STAC API versions >= 0.9.0 (preferrably [STAC API version 1.0.0](https://github.com/radiantearth/stac-api-spec/blob/v1.0.0/README.md), but [0.9.0](https://github.com/radiantearth/stac-spec/blob/v0.9.0/api-spec/README.md) is allowed for backward compatibility), which allows to serve all STAC specification versions in the range of 0.9.x and 1.x.x (see the `stac_version` property).\n\n### Content Extensions\n\nSTAC has several [extensions](https://stac-extensions.github.io) that can be used to better describe your data. Clients and server are not required to implement all of them, so be aware that some clients may not be able to read all your metadata.\n\nSome commonly used extensions that are relevant for datasets exposed through the openEO API are:\n\n- Data Cube extension (part of the openEO API)\n- [EO (Electro-Optical) extension](https://github.com/stac-extensions/eo)\n- [Processing extension](https://github.com/stac-extensions/processing)\n- [Raster extension](https://github.com/stac-extensions/raster)\n- [SAR extension](https://github.com/stac-extensions/sar)\n- [Satellite extension](https://github.com/stac-extensions/sat)\n- [Scientific Citation extension](https://github.com/stac-extensions/scientific)\n\n### Provide data for download\n\nIf you'd like to provide your data for download in addition to offering the cloud processing service, you can implement the full STAC API. Therefore you can implement the endpoints `GET /collections/{collection_id}/items` and `GET /collections/{collection_id}/items/{feature_id}` to support retrieval of individual items. To benefit from the STAC ecosystem and allow searching for items you can also implement `POST /search` and `GET /search`. Further information can be found in the [STAC API repository](https://github.com/radiantearth/stac-spec/tree/v0.9.0/api-spec).\n\n### API Extensions\n\nSTAC API has several [extensions](https://stac-api-extensions.github.io) that can be implemented on top of the openEO API to enrich the API functionality, e.g. for searching." + }, + { + "name": "Process Discovery", + "description": "These endpoints allow to list the predefined processes that are available at the back-end. To list user-defined processes see '[User-Defined Processes](#tag/User-Defined-Processes)'." + }, + { + "name": "User-Defined Processes", + "description": "These endpoints allow to store and manage user-defined processes with their process graphs at the back-end." + }, + { + "name": "Data Processing", + "description": "Organizes and manages data processing on the back-end, either as synchronous on-demand computation or batch jobs." + }, + { + "name": "Batch Jobs", + "description": "Management of batch processing tasks (jobs) and their results." + }, + { + "name": "Secondary Services", + "description": "On-demand access to data using other web service protocols." + }, + { + "name": "File Storage", + "description": "Management of user-uploaded assets and processed data." + } ], "servers": [ - { - "url": "https://openeo-dev.eodc.eu/openeo/1.1.0/", - "description": "The URL of the API MAY freely be chosen by the back-end providers. The path, including API versioning, is a *recommendation* only. Nevertheless, all servers MUST support HTTPS as the authentication methods are not secure with HTTP only!", - "variables": { - "version": { - "default": "v1", - "description": "API versioning is RECOMMENDED. As the openEO API is following\n[SemVer](https://semver.org/) only the **major** part of the version\nnumbers SHOULD be used for API versioning in the URL. To make clear\nthat it is a version number, it is RECOMMENDED to add the prefix `v`.\n\nExample: API version `1.2.3` is recommended to use `v1`.\n\nThe reason to only consider the major part is that backward-incompatible\nchanges are introduced by major changes only. All changes from minor\nand patch releases can usually be integrated without breakages and thus\na change in the URL is not really needed.\n\nThe version number in the URL MUST not be used by the clients to detect\nthe version number of the API. Use the version number returned in the\nproperty `api_version` from `GET /` instead." - } - } + { + "url": "https://openeo.example/api/{version}", + "description": "The URL of the API MAY freely be chosen by the back-end providers. The path, including API versioning, is a *recommendation* only. Nevertheless, all servers MUST support HTTPS as the authentication methods are not secure with HTTP only!", + "variables": { + "version": { + "default": "v1", + "description": "API versioning is RECOMMENDED. As the openEO API is following\n[SemVer](https://semver.org/) only the **major** part of the version\nnumbers SHOULD be used for API versioning in the URL. To make clear\nthat it is a version number, it is RECOMMENDED to add the prefix `v`.\n\nExample: API version `1.2.3` is recommended to use `v1`.\n\nThe reason to only consider the major part is that backward-incompatible\nchanges are introduced by major changes only. All changes from minor\nand patch releases can usually be integrated without breakages and thus\na change in the URL is not really needed.\n\nThe version number in the URL MUST not be used by the clients to detect\nthe version number of the API. Use the version number returned in the\nproperty `api_version` from `GET /` instead." + } } + } ], "paths": { - "/": { - "get": { - "summary": "Information about the back-end", - "operationId": "capabilities", - "description": "Lists general information about the back-end, including which version and endpoints of the openEO API are supported. May also include billing information.", - "tags": [ - "Capabilities" - ], - "security": [ - {} - ], - "responses": { - "200": { - "description": "Information about the API version and supported endpoints /\nfeatures.\n\nThis endpoint MUST always be available for the API to be valid.", - "content": { - "application/json": { - "schema": { - "title": "Capabilities", - "type": "object", - "required": [ - "id", - "title", - "description", - "api_version", - "backend_version", - "stac_version", - "endpoints", - "links" - ], - "properties": { - "api_version": { - "type": "string", - "description": "Version number of the openEO specification this back-end implements.", - "enum": [ - "1.2.0" - ] - }, - "backend_version": { - "type": "string", - "description": "Version number of the back-end implementation.\nEvery change on back-end side MUST cause a change of the version number.", - "example": "1.1.2" - }, - "stac_version": { - "$ref": "#/components/schemas/stac_version" - }, - "type": { - "type": "string", - "enum": [ - "Catalog" - ], - "description": "For STAC versions >= 1.0.0-rc.1 this field is required.", - "example": "Catalog" - }, - "id": { - "type": "string", - "description": "Identifier for the service.\nThis field originates from STAC and is used as unique identifier for the STAC catalog available at `/collections`.", - "example": "cool-eo-cloud" - }, - "title": { - "type": "string", - "description": "The name of the service.", - "example": "Example Cloud Corp." - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "A description of the service, which allows the service provider to introduce the user to its service.\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", - "example": "This service is provided to you by [Example Cloud Corp.](https://cloud.example). It implements the full openEO API and allows to process a range of 999 EO data sets, including \n\n* Sentinel 1/2/3 and 5\n* Landsat 7/8\n\nA free plan is available to test the service. For further information please contact our customer service at [support@cloud.example](mailto:support@cloud.example)." - }, - "conformsTo": { - "$ref": "#/components/schemas/conformsTo" - }, - "production": { - "$ref": "#/components/schemas/production" - }, - "endpoints": { - "type": "array", - "description": "Lists all supported endpoints. Supported are all endpoints, which are implemented, return usually a 2XX or 3XX HTTP status code and are fully compatible to the API specification. An entry for this endpoint (path `/` with method `GET`) SHOULD NOT be listed. Each path MUST only be listed once in the array.", - "items": { - "title": "Endpoint", - "type": "object", - "required": [ - "path", - "methods" - ], - "properties": { - "path": { - "description": "Path to the endpoint, relative to the URL of this endpoint. In general the paths MUST follow the paths specified in the openAPI specification as closely as possible. Therefore, paths MUST be prepended with a leading slash, but MUST NOT contain a trailing slash. Variables in the paths MUST be placed in curly braces and follow the parameter names in the openAPI specification, e.g. `{job_id}`.", - "type": "string" - }, - "methods": { - "description": "Supported HTTP verbs in uppercase. It is OPTIONAL to list `OPTIONS` as method (see the [CORS section](#section/Cross-Origin-Resource-Sharing-(CORS))).", - "type": "array", - "items": { - "type": "string", - "enum": [ - "GET", - "POST", - "PATCH", - "PUT", - "DELETE", - "OPTIONS" - ] - } - } - } - }, - "example": [ - { - "path": "/collections", - "methods": [ - "GET" - ] - }, - { - "path": "/collections/{collection_id}", - "methods": [ - "GET" - ] - }, - { - "path": "/processes", - "methods": [ - "GET" - ] - }, - { - "path": "/jobs", - "methods": [ - "GET", - "POST" - ] - }, - { - "path": "/jobs/{job_id}", - "methods": [ - "GET", - "DELETE", - "PATCH" - ] - } - ] - }, - "billing": { - "title": "Billing", - "description": "Billing related data, e.g. the currency used or available plans to process jobs.\nThis property MUST be specified if the back-end uses any billing related API functionalities, e.g. budgeting or estimates.\nThe absence of this property doesn't mean the back-end is necessarily free to use for all. Providers may choose to bill users outside of the API, e.g. with a monthly fee that is not depending on individual API interactions.", - "type": "object", - "required": [ - "currency" - ], - "properties": { - "currency": { - "description": "The currency the back-end is billing in. The currency MUST be either a valid currency code as defined in ISO-4217 or a back-end specific unit that is used for billing such as credits, tiles or CPU hours. If set to `null`, budget and costs are not supported by the back-end and users can't be charged.", - "type": "string", - "nullable": true, - "example": "USD" - }, - "default_plan": { - "type": "string", - "description": "Name of the plan the back-end uses for billing in case \n1. the user has not subscribed to a specific plan\n (see `default_plan` in `GET /me`) and\n2. also did not provide a specific plan with the\n processing request.\n\nIf a free plan is available at the back-end, it is \nprobably most useful to provide this as the back-end\nwide default plan and override it with paid plans through\nthe user-specific default plan in `GET /me`.\nOtherwise, users that have not set up payment yet MAY\nreceive an error for each processing requests where\nthey did not provide a free plan specifically.", - "example": "free" - }, - "plans": { - "description": "Array of plans", - "type": "array", - "items": { - "title": "Billing Plan", - "type": "object", - "required": [ - "name", - "description", - "paid" - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the plan. It MUST be accepted in a *case insensitive* manner throughout the API.", - "example": "free" - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "A description that gives a rough overview over the plan.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", - "example": "Free plan for testing." - }, - "paid": { - "type": "boolean", - "description": "Indicates whether the plan is a paid plan (`true`) or a free plan (`false`)." - }, - "url": { - "type": "string", - "description": "URL to a web page with more details about the plan.", - "format": "uri", - "example": "https://cloud.example/plans/free-plan" - } - } - }, - "example": [ - { - "name": "free", - "description": "Free plan. Calculates one tile per second and a maximum amount of 100 tiles per hour.", - "url": "https://cloud.example/plans/free-plan", - "paid": false - }, - { - "name": "premium", - "description": "Premium plan. Calculates unlimited tiles and each calculated tile costs 0.003 USD.", - "url": "https://cloud.example/plans/premium-plan", - "paid": true - } - ] - } - } - }, - "links": { - "description": "Links related to this service, e.g. the homepage of\nthe service provider or the terms of service.\n\nIt is highly RECOMMENDED to provide links with the\nfollowing `rel` (relation) types:\n\n1. `version-history`: A link back to the Well-Known URL\n(including `/.well-known/openeo`, see the corresponding endpoint for details)\nto allow clients to work on the most recent version.\n\n2. `terms-of-service`: A link to the terms of service. If\na back-end provides a link to the terms of service, the\nclients MUST provide a way to read the terms of service\nand only connect to the back-end after the user agreed to\nthem. The user interface MUST be designed in a way that\nthe terms of service are not agreed to by default, i.e.\nthe user MUST explicitly agree to them.\n\n3. `privacy-policy`: A link to the privacy policy (GDPR).\nIf a back-end provides a link to a privacy policy, the\nclients MUST provide a way to read the privacy policy and\nonly connect to the back-end after the user agreed to\nthem. The user interface MUST be designed in a way that\nthe privacy policy is not agreed to by default, i.e. the\nuser MUST explicitly agree to them.\n\n4. `service-desc` or `service-doc`: A link to the API definition.\nUse `service-desc` for machine-readable API definition and \n`service-doc` for human-readable API definition.\nRequired if full OGC API compatibility is desired.\n\n5. `conformance`: A link to the Conformance declaration\n(see `/conformance`). \nRequired if full OGC API compatibility is desired.\n\n6. `data`: A link to the collections (see `/collections`).\nRequired if full OGC API compatibility is desired.\n\n7. `create-form`: A link to a user registration page.\n\n8. `recovery-form`: A link to a page where a user can\nrecover a user account (e.g. to reset the password or send\na reminder about the username to the user's email account).\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "href": "https://cloud.example", - "rel": "about", - "type": "text/html", - "title": "Homepage of the service provider" - }, - { - "href": "https://cloud.example/tos", - "rel": "terms-of-service", - "type": "text/html", - "title": "Terms of Service" - }, - { - "href": "https://cloud.example/privacy", - "rel": "privacy-policy", - "type": "text/html", - "title": "Privacy Policy" - }, - { - "href": "https://cloud.example/register", - "rel": "create-form", - "type": "text/html", - "title": "User Registration" - }, - { - "href": "https://cloud.example/lost-password", - "rel": "recovery-form", - "type": "text/html", - "title": "Reset Password" - }, - { - "href": "https://cloud.example/.well-known/openeo", - "rel": "version-history", - "type": "application/json", - "title": "List of supported openEO versions" - }, - { - "href": "https://cloud.example/api/v1/conformance", - "rel": "conformance", - "type": "application/json", - "title": "OGC Conformance Classes" - }, - { - "href": "https://cloud.example/api/v1/collections", - "rel": "data", - "type": "application/json", - "title": "List of Datasets" - } - ] - } - } - } + "/": { + "get": { + "summary": "Information about the back-end", + "operationId": "capabilities", + "description": "Lists general information about the back-end, including which version and endpoints of the openEO API are supported. May also include billing information.", + "tags": [ + "Capabilities" + ], + "security": [ + {} + ], + "responses": { + "200": { + "description": "Information about the API version and supported endpoints /\nfeatures.\n\nThis endpoint MUST always be available for the API to be valid.", + "content": { + "application/json": { + "schema": { + "title": "Capabilities", + "type": "object", + "required": [ + "id", + "title", + "description", + "api_version", + "backend_version", + "stac_version", + "endpoints", + "links" + ], + "properties": { + "api_version": { + "type": "string", + "description": "Version number of the openEO specification this back-end implements.", + "enum": [ + "1.2.0" + ] + }, + "backend_version": { + "type": "string", + "description": "Version number of the back-end implementation.\nEvery change on back-end side MUST cause a change of the version number.", + "example": "1.1.2" + }, + "stac_version": { + "$ref": "#/components/schemas/stac_version" + }, + "type": { + "type": "string", + "enum": [ + "Catalog" + ], + "description": "For STAC versions >= 1.0.0-rc.1 this field is required.", + "example": "Catalog" + }, + "id": { + "type": "string", + "description": "Identifier for the service.\nThis field originates from STAC and is used as unique identifier for the STAC catalog available at `/collections`.", + "example": "cool-eo-cloud" + }, + "title": { + "type": "string", + "description": "The name of the service.", + "example": "Example Cloud Corp." + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "A description of the service, which allows the service provider to introduce the user to its service.\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", + "example": "This service is provided to you by [Example Cloud Corp.](https://cloud.example). It implements the full openEO API and allows to process a range of 999 EO data sets, including \n\n* Sentinel 1/2/3 and 5\n* Landsat 7/8\n\nA free plan is available to test the service. For further information please contact our customer service at [support@cloud.example](mailto:support@cloud.example)." + }, + "conformsTo": { + "$ref": "#/components/schemas/conformsTo" + }, + "production": { + "$ref": "#/components/schemas/production" + }, + "endpoints": { + "type": "array", + "description": "Lists all supported endpoints. Supported are all endpoints, which are implemented, return usually a 2XX or 3XX HTTP status code and are fully compatible to the API specification. An entry for this endpoint (path `/` with method `GET`) SHOULD NOT be listed. Each path MUST only be listed once in the array.", + "items": { + "title": "Endpoint", + "type": "object", + "required": [ + "path", + "methods" + ], + "properties": { + "path": { + "description": "Path to the endpoint, relative to the URL of this endpoint. In general the paths MUST follow the paths specified in the openAPI specification as closely as possible. Therefore, paths MUST be prepended with a leading slash, but MUST NOT contain a trailing slash. Variables in the paths MUST be placed in curly braces and follow the parameter names in the openAPI specification, e.g. `{job_id}`.", + "type": "string" + }, + "methods": { + "description": "Supported HTTP verbs in uppercase. It is OPTIONAL to list `OPTIONS` as method (see the [CORS section](#section/Cross-Origin-Resource-Sharing-(CORS))).", + "type": "array", + "items": { + "type": "string", + "enum": [ + "GET", + "POST", + "PATCH", + "PUT", + "DELETE", + "OPTIONS" + ] + } } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/.well-known/openeo": { - "get": { - "summary": "Supported openEO versions", - "operationId": "connect", - "description": "Lists all implemented openEO versions supported by the\nservice provider. This endpoint is the Well-Known URI\n(see [RFC 5785](https://www.rfc-editor.org/rfc/rfc5785.html)) for openEO.\n\nThis allows a client to easily identify the most recent openEO\nimplementation it supports. By default, a client SHOULD connect to the\nmost recent production-ready version it supports. If not available, the\nmost recent supported version of *all* versions SHOULD be connected to.\nClients MAY let users choose to connect to versions that are not\nproduction-ready or outdated.\nThe most recent version is determined by comparing the version numbers\naccording to rules from [Semantic Versioning](https://semver.org/),\nespecially [\u00a711](https://semver.org/#spec-item-11). Any pair of API\nversions in this list MUST NOT be equal according to Semantic Versioning.\n\nThe Well-Known URI is the entry point for clients and users, so make\nsure it is permanent and easy to use and remember. Clients MUST NOT\nrequire the well-known path (`/.well-known/openeo`) in the URL that is\nspecified by a user to connect to the back-end.\n\nFor clients, the usual behavior SHOULD follow these steps:\n1. The user provides a URI, which may consist of a scheme (protocol), \n an authority (host, port) and a path.\n2. The client parses the URI and appends `/.well-knwon/openeo` to the\n path. Make sure to correctly handle leading/trailing slashes.\n3. Send a request to the new URI.\n A. On success: Detect the most suitable API instance/version (see above)\n and read the [capabilites](#tag/Capabilities/operation/capabilities)\n from there.\n B. On failure: Directly try to read the capabilities from the original URI\n given by the user.\n\n**This URI MUST NOT be versioned as the other endpoints.**\nIf your API is available at `https://openeo.example/api/v1`, and\nyou instruct your API users to use `https://openeo.example` as connection URI, \nthe Well-Known URI SHOULD be located at `https://openeo.example/.well-known/openeo`.\nThe Well-Known URI is usually directly located at the top-level, but it is not a\nrequirement. For example, `https://openeo.example/eo/.well-known/openeo` is also allowed.\n\nClients MAY get additional information (e.g. title or description) about\na back-end from the most recent version that has the `production` flag\nset to `true`.", - "tags": [ - "Capabilities" - ], - "security": [ - {} - ], - "servers": [ - { - "url": "https://openeo-dev.eodc.eu/", - "description": "The Well-Known URI SHOULD be available directly at `https://{{domain}}/.well-known/openeo` in contrast to the other endpoints, which may be versioned and can run on other hosts, ports, ... etc." - } - ], - "responses": { - "200": { - "description": "List of all available API instances, each with URL and the implemented openEO API version.", - "content": { - "application/json": { - "schema": { - "title": "Well Known Discovery", - "type": "object", - "required": [ - "versions" - ], - "properties": { - "versions": { - "type": "array", - "items": { - "title": "API Instance", - "type": "object", - "required": [ - "url", - "api_version" - ], - "properties": { - "url": { - "type": "string", - "format": "uri", - "description": "*Absolute* URLs to the service.", - "example": "https://openeo.example/api/v1" - }, - "production": { - "$ref": "#/components/schemas/production" - }, - "api_version": { - "type": "string", - "description": "Version number of the openEO specification this back-end implements." - } - } - } - } - } + } + }, + "example": [ + { + "path": "/collections", + "methods": [ + "GET" + ] + }, + { + "path": "/collections/{collection_id}", + "methods": [ + "GET" + ] + }, + { + "path": "/processes", + "methods": [ + "GET" + ] + }, + { + "path": "/jobs", + "methods": [ + "GET", + "POST" + ] + }, + { + "path": "/jobs/{job_id}", + "methods": [ + "GET", + "DELETE", + "PATCH" + ] + } + ] + }, + "billing": { + "title": "Billing", + "description": "Billing related data, e.g. the currency used or available plans to process jobs.\nThis property MUST be specified if the back-end uses any billing related API functionalities, e.g. budgeting or estimates.\nThe absence of this property doesn't mean the back-end is necessarily free to use for all. Providers may choose to bill users outside of the API, e.g. with a monthly fee that is not depending on individual API interactions.", + "type": "object", + "required": [ + "currency" + ], + "properties": { + "currency": { + "description": "The currency the back-end is billing in. The currency MUST be either a valid currency code as defined in ISO-4217 or a back-end specific unit that is used for billing such as credits, tiles or CPU hours. If set to `null`, budget and costs are not supported by the back-end and users can't be charged.", + "type": "string", + "nullable": true, + "example": "USD" + }, + "default_plan": { + "type": "string", + "description": "Name of the plan the back-end uses for billing in case \n1. the user has not subscribed to a specific plan\n (see `default_plan` in `GET /me`) and\n2. also did not provide a specific plan with the\n processing request.\n\nIf a free plan is available at the back-end, it is \nprobably most useful to provide this as the back-end\nwide default plan and override it with paid plans through\nthe user-specific default plan in `GET /me`.\nOtherwise, users that have not set up payment yet MAY\nreceive an error for each processing requests where\nthey did not provide a free plan specifically.", + "example": "free" + }, + "plans": { + "description": "Array of plans", + "type": "array", + "items": { + "title": "Billing Plan", + "type": "object", + "required": [ + "name", + "description", + "paid" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of the plan. It MUST be accepted in a *case insensitive* manner throughout the API.", + "example": "free" }, - "example": { - "versions": [ - { - "url": "https://openeo.example/api/v0", - "api_version": "0.5.1" - }, - { - "url": "https://openeo.example/api/v1", - "api_version": "1.2.0" - }, - { - "url": "https://dev.openeo.example/api/v2", - "production": false, - "api_version": "2.0.0-beta" - } - ] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/file_formats": { - "get": { - "summary": "Supported file formats", - "operationId": "list-file-types", - "description": "Lists supported input and output file formats.\n*Input* file formats specify which file a back-end can *read* from.\n*Output* file formats specify which file a back-end can *write* to.\n\nThe response to this request is an object listing all available input\nand output file formats separately with their parameters and additional\ndata. This endpoint does not include the supported secondary web\nservices.\n\n**Note**: Format names and parameters MUST be fully aligned with the\nGDAL codes if available, see [GDAL Raster\nFormats](https://gdal.org/drivers/raster/index.html) and [OGR Vector\nFormats](https://gdal.org/drivers/vector/index.html). It is OPTIONAL to\nsupport all output format parameters supported by GDAL. Some file\nformats not available through GDAL may be defined centrally for openEO.\nCustom file formats or parameters MAY be defined.\n\nThe format descriptions must describe how the file formats relate to \ndata cubes. Input file formats must describe how the files have to be\nstructured to be transformed into data cubes. Output file formats must\ndescribe how the data cubes are stored at the back-end and how the \nresulting file structure looks like.\n\nBack-ends MUST NOT support aliases, for example it is not allowed to\nsupport `geotiff` instead of `gtiff`. Nevertheless, openEO Clients MAY\ntranslate user input input for convenience (e.g. translate `geotiff` to\n`gtiff`). Also, for a better user experience the back-end can specify a\n`title`.\n\nFormat names MUST be accepted in a *case insensitive* manner throughout the API.", - "tags": [ - "Capabilities", - "Data Processing" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "An object with containing all input and output format separately. For each property `input` and `output` an object is defined where the file format names are the property keys and the property values are objects that define a title, supported parameters and related links.", - "content": { - "application/json": { - "schema": { - "title": "File Formats", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "title": "Input File Formats", - "type": "object", - "description": "Map of supported input file formats, i.e. file formats a back-end can **read** from. The property keys are the file format names that are used by clients and users, for example in process graphs.", - "additionalProperties": { - "$ref": "#/components/schemas/file_format" - } - }, - "output": { - "title": "Output File Formats", - "type": "object", - "description": "Map of supported output file formats, i.e. file formats a back-end can **write** to. The property keys are the file format names that are used by clients and users, for example in process graphs.", - "additionalProperties": { - "$ref": "#/components/schemas/file_format" - } - } - } + "description": { + "type": "string", + "format": "commonmark", + "description": "A description that gives a rough overview over the plan.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", + "example": "Free plan for testing." }, - "example": { - "output": { - "GTiff": { - "title": "GeoTiff", - "description": "Export to GeoTiff. Doesn't support cloud-optimized GeoTiffs (COGs) yet.", - "gis_data_types": [ - "raster" - ], - "parameters": { - "tiled": { - "type": "boolean", - "description": "This option can be used to force creation of tiled TIFF files [true]. By default [false] stripped TIFF files are created.", - "default": false - }, - "compress": { - "type": "string", - "description": "Set the compression to use.", - "default": "NONE", - "enum": [ - "JPEG", - "LZW", - "DEFLATE", - "NONE" - ] - }, - "jpeg_quality": { - "type": "integer", - "description": "Set the JPEG quality when using JPEG.", - "minimum": 1, - "maximum": 100, - "default": 75 - } - }, - "links": [ - { - "href": "https://gdal.org/drivers/raster/gtiff.html", - "rel": "about", - "title": "GDAL on the GeoTiff file format and storage options" - } - ] - }, - "GPKG": { - "title": "OGC GeoPackage", - "gis_data_types": [ - "raster", - "vector" - ], - "parameters": { - "version": { - "type": "string", - "description": "Set GeoPackage version. In AUTO mode, this will be equivalent to 1.2 starting with GDAL 2.3.", - "enum": [ - "auto", - "1", - "1.1", - "1.2" - ], - "default": "auto" - } - }, - "links": [ - { - "href": "https://gdal.org/drivers/raster/gpkg.html", - "rel": "about", - "title": "GDAL on GeoPackage for raster data" - }, - { - "href": "https://gdal.org/drivers/vector/gpkg.html", - "rel": "about", - "title": "GDAL on GeoPackage for vector data" - } - ] - } - }, - "input": { - "GPKG": { - "title": "OGC GeoPackage", - "gis_data_types": [ - "raster", - "vector" - ], - "parameters": { - "table": { - "type": "string", - "description": "**RASTER ONLY.** Name of the table containing the tiles. If the GeoPackage dataset only contains one table, this option is not necessary. Otherwise, it is required." - } - }, - "links": [ - { - "href": "https://gdal.org/drivers/raster/gpkg.html", - "rel": "about", - "title": "GDAL on GeoPackage for raster data" - }, - { - "href": "https://gdal.org/drivers/vector/gpkg.html", - "rel": "about", - "title": "GDAL on GeoPackage for vector data" - } - ] - } - } + "paid": { + "type": "boolean", + "description": "Indicates whether the plan is a paid plan (`true`) or a free plan (`false`)." + }, + "url": { + "type": "string", + "description": "URL to a web page with more details about the plan.", + "format": "uri", + "example": "https://cloud.example/plans/free-plan" } - } + } + }, + "example": [ + { + "name": "free", + "description": "Free plan. Calculates one tile per second and a maximum amount of 100 tiles per hour.", + "url": "https://cloud.example/plans/free-plan", + "paid": false + }, + { + "name": "premium", + "description": "Premium plan. Calculates unlimited tiles and each calculated tile costs 0.003 USD.", + "url": "https://cloud.example/plans/premium-plan", + "paid": true + } + ] + } } - }, - "4XX": { - "$ref": "#/components/responses/client_error" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + }, + "links": { + "description": "Links related to this service, e.g. the homepage of\nthe service provider or the terms of service.\n\nIt is highly RECOMMENDED to provide links with the\nfollowing `rel` (relation) types:\n\n1. `version-history`: A link back to the Well-Known URL\n(including `/.well-known/openeo`, see the corresponding endpoint for details)\nto allow clients to work on the most recent version.\n\n2. `terms-of-service`: A link to the terms of service. If\na back-end provides a link to the terms of service, the\nclients MUST provide a way to read the terms of service\nand only connect to the back-end after the user agreed to\nthem. The user interface MUST be designed in a way that\nthe terms of service are not agreed to by default, i.e.\nthe user MUST explicitly agree to them.\n\n3. `privacy-policy`: A link to the privacy policy (GDPR).\nIf a back-end provides a link to a privacy policy, the\nclients MUST provide a way to read the privacy policy and\nonly connect to the back-end after the user agreed to\nthem. The user interface MUST be designed in a way that\nthe privacy policy is not agreed to by default, i.e. the\nuser MUST explicitly agree to them.\n\n4. `service-desc` or `service-doc`: A link to the API definition.\nUse `service-desc` for machine-readable API definition and \n`service-doc` for human-readable API definition.\nRequired if full OGC API compatibility is desired.\n\n5. `conformance`: A link to the Conformance declaration\n(see `/conformance`). \nRequired if full OGC API compatibility is desired.\n\n6. `data`: A link to the collections (see `/collections`).\nRequired if full OGC API compatibility is desired.\n\n7. `create-form`: A link to a user registration page.\n\n8. `recovery-form`: A link to a page where a user can\nrecover a user account (e.g. to reset the password or send\na reminder about the username to the user's email account).\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "href": "https://cloud.example", + "rel": "about", + "type": "text/html", + "title": "Homepage of the service provider" + }, + { + "href": "https://cloud.example/tos", + "rel": "terms-of-service", + "type": "text/html", + "title": "Terms of Service" + }, + { + "href": "https://cloud.example/privacy", + "rel": "privacy-policy", + "type": "text/html", + "title": "Privacy Policy" + }, + { + "href": "https://cloud.example/register", + "rel": "create-form", + "type": "text/html", + "title": "User Registration" + }, + { + "href": "https://cloud.example/lost-password", + "rel": "recovery-form", + "type": "text/html", + "title": "Reset Password" + }, + { + "href": "https://cloud.example/.well-known/openeo", + "rel": "version-history", + "type": "application/json", + "title": "List of supported openEO versions" + }, + { + "href": "https://cloud.example/api/v1/conformance", + "rel": "conformance", + "type": "application/json", + "title": "OGC Conformance Classes" + }, + { + "href": "https://cloud.example/api/v1/collections", + "rel": "data", + "type": "application/json", + "title": "List of Datasets" + } + ] + } } + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/conformance": { - "get": { - "summary": "Conformance classes this API implements", - "operationId": "conformance", - "description": "Lists all conformance classes specified in various standards that the\nimplementation conforms to. Conformance classes are commonly used in\nall OGC APIs and the STAC API specification. openEO adds relatively\nbroadly defined conformance classes, especially for the extensions.\nOtherwise, the implemented functionality can usually be retrieved from\nthe [capabilties](#tag/Capabilities/operation/capabilities) in openEO.\n\nThe general openEO conformance class is `https://api.openeo.org/1.2.0`.\nSee the individual openEO API extensions for their conformance classes.\n\nThe conformance classes listed at this endpoint and listed in the \ncorresponding `conformsTo` property in `GET /` MUST be equal.\n\nMore details:\n- [STAC API](https://github.com/radiantearth/stac-api-spec), especially the conformance class \"STAC API - Collections\"\n- [OGC APIs](https://ogcapi.ogc.org/)", - "tags": [ - "Capabilities" - ], - "responses": { - "200": { - "description": "The URIs of all conformance classes supported by the server.", - "content": { - "application/json": { - "schema": { - "title": "OGC Conformance Classes", - "type": "object", - "required": [ - "conformsTo" - ], - "properties": { - "conformsTo": { - "$ref": "#/components/schemas/conformsTo" - } - } - } - } - } - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } + } + } + }, + "/.well-known/openeo": { + "get": { + "summary": "Supported openEO versions", + "operationId": "connect", + "description": "Lists all implemented openEO versions supported by the\nservice provider. This endpoint is the Well-Known URI\n(see [RFC 5785](https://www.rfc-editor.org/rfc/rfc5785.html)) for openEO.\n\nThis allows a client to easily identify the most recent openEO\nimplementation it supports. By default, a client SHOULD connect to the\nmost recent production-ready version it supports. If not available, the\nmost recent supported version of *all* versions SHOULD be connected to.\nClients MAY let users choose to connect to versions that are not\nproduction-ready or outdated.\nThe most recent version is determined by comparing the version numbers\naccording to rules from [Semantic Versioning](https://semver.org/),\nespecially [§11](https://semver.org/#spec-item-11). Any pair of API\nversions in this list MUST NOT be equal according to Semantic Versioning.\n\nThe Well-Known URI is the entry point for clients and users, so make\nsure it is permanent and easy to use and remember. Clients MUST NOT\nrequire the well-known path (`/.well-known/openeo`) in the URL that is\nspecified by a user to connect to the back-end.\n\nFor clients, the usual behavior SHOULD follow these steps:\n1. The user provides a URI, which may consist of a scheme (protocol), \n an authority (host, port) and a path.\n2. The client parses the URI and appends `/.well-knwon/openeo` to the\n path. Make sure to correctly handle leading/trailing slashes.\n3. Send a request to the new URI.\n A. On success: Detect the most suitable API instance/version (see above)\n and read the [capabilites](#tag/Capabilities/operation/capabilities)\n from there.\n B. On failure: Directly try to read the capabilities from the original URI\n given by the user.\n\n**This URI MUST NOT be versioned as the other endpoints.**\nIf your API is available at `https://openeo.example/api/v1`, and\nyou instruct your API users to use `https://openeo.example` as connection URI, \nthe Well-Known URI SHOULD be located at `https://openeo.example/.well-known/openeo`.\nThe Well-Known URI is usually directly located at the top-level, but it is not a\nrequirement. For example, `https://openeo.example/eo/.well-known/openeo` is also allowed.\n\nClients MAY get additional information (e.g. title or description) about\na back-end from the most recent version that has the `production` flag\nset to `true`.", + "tags": [ + "Capabilities" + ], + "security": [ + {} + ], + "servers": [ + { + "url": "https://openeo.example", + "description": "The Well-Known URI SHOULD be available directly at `https://{{domain}}/.well-known/openeo` in contrast to the other endpoints, which may be versioned and can run on other hosts, ports, ... etc." } - }, - "/collections": { - "get": { - "summary": "Basic metadata for all datasets", - "operationId": "list-collections", - "description": "Lists available collections with at least the required information.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting larger optional values from the objects in `collections` (e.g. the\n`summaries` and `cube:dimensions` properties).\nTo get the full metadata for a collection clients MUST\nrequest `GET /collections/{collection_id}`.\n\nThis endpoint is compatible with [STAC API 0.9.0 and later](https://stacspec.org) and\n[OGC API - Features 1.0](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html).\n[STAC API extensions](https://stac-api-extensions.github.io) and\n[STAC extensions](https://stac-extensions.github.io)\ncan be implemented in addition to what is documented here.\n\nNote: Although it is possible to request public collections without\nauthorization, it is RECOMMENDED that clients (re-)request the collections\nwith the Bearer token once available to also retrieve any private collections.", - "tags": [ - "EO Data Discovery" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Lists of collections and related links.", - "content": { - "application/json": { - "schema": { - "title": "Collections", - "type": "object", - "required": [ - "collections", - "links" - ], - "properties": { - "collections": { - "type": "array", - "items": { - "$ref": "#/components/schemas/collection" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - }, - "example": { - "collections": [ - { - "stac_version": "1.0.0", - "type": "Collection", - "id": "Sentinel-2A", - "title": "Sentinel-2A MSI L1C", - "description": "Sentinel-2A is a wide-swath, high-resolution, multi-spectral imaging mission supporting Copernicus Land Monitoring studies, including the monitoring of vegetation, soil and water cover, as well as observation of inland waterways and coastal areas.", - "license": "proprietary", - "extent": { - "spatial": { - "bbox": [ - [ - -180, - -56, - 180, - 83 - ] - ] - }, - "temporal": { - "interval": [ - [ - "2015-06-23T00:00:00Z", - "2019-01-01T00:00:00Z" - ] - ] - } - }, - "keywords": [ - "copernicus", - "esa", - "msi", - "sentinel" - ], - "providers": [ - { - "name": "European Space Agency (ESA)", - "roles": [ - "producer", - "licensor" - ], - "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" - }, - { - "name": "openEO", - "roles": [ - "host" - ], - "url": "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2" - } - ], - "links": [ - { - "rel": "license", - "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf" - } - ] - }, - { - "stac_version": "1.0.0", - "type": "Collection", - "id": "MOD09Q1", - "title": "MODIS/Terra Surface Reflectance 8-Day L3 Global 250m SIN Grid V006", - "description": "The MOD09Q1 Version 6 product provides an estimate of the surface spectral reflectance of Terra MODIS Bands 1-2 corrected for atmospheric conditions such as gasses, aerosols, and Rayleigh scattering. Provided along with the two 250 m MODIS bands is one additional layer, the Surface Reflectance QC 250 m band. For each pixel, a value is selected from all the acquisitions within the 8-day composite period. The criteria for the pixel choice include cloud and solar zenith. When several acquisitions meet the criteria the pixel with the minimum channel 3 (blue) value is used. Validation at stage 3 has been achieved for all MODIS Surface Reflectance products.", - "license": "proprietary", - "extent": { - "spatial": { - "bbox": [ - [ - -180, - -90, - 180, - 90 - ] - ] - }, - "temporal": { - "interval": [ - [ - "2000-02-01T00:00:00Z", - null - ] - ] - } - }, - "links": [ - { - "rel": "license", - "href": "https://openeo.example/api/v1/collections/MOD09Q1/license" - } - ] - } - ], - "links": [ - { - "rel": "alternate", - "href": "https://openeo.example/csw", - "title": "openEO catalog (OGC Catalogue Services 3.0)" - } - ] - } + ], + "responses": { + "200": { + "description": "List of all available API instances, each with URL and the implemented openEO API version.", + "content": { + "application/json": { + "schema": { + "title": "Well Known Discovery", + "type": "object", + "required": [ + "versions" + ], + "properties": { + "versions": { + "type": "array", + "items": { + "title": "API Instance", + "type": "object", + "required": [ + "url", + "api_version" + ], + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "*Absolute* URLs to the service.", + "example": "https://openeo.example/api/v1" + }, + "production": { + "$ref": "#/components/schemas/production" + }, + "api_version": { + "type": "string", + "description": "Version number of the openEO specification this back-end implements." } + } } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } + } + } + }, + "example": { + "versions": [ + { + "url": "https://openeo.example/api/v0", + "api_version": "0.5.1" + }, + { + "url": "https://openeo.example/api/v1", + "api_version": "1.2.0" + }, + { + "url": "https://dev.openeo.example/api/v2", + "production": false, + "api_version": "2.0.0-beta" + } + ] + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/collections/{collection_id}": { - "get": { - "summary": "Full metadata for a specific dataset", - "operationId": "describe-collection", - "description": "Lists **all** information about a specific collection specified by the\nidentifier `collection_id`.\n\nThis endpoint is compatible with [STAC API 0.9.0 and later](https://stacspec.org) and\n[OGC API - Features 1.0](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html).\n[STAC API extensions](https://stac-api-extensions.github.io) and\n[STAC extensions](https://stac-extensions.github.io)\ncan be implemented in addition to what is documented here.\n\nNote: Providing the Bearer token is REQUIRED for private collections.", - "tags": [ - "EO Data Discovery" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/collection_id" - } - ], - "responses": { - "200": { - "description": "JSON object with the full collection metadata.", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "cube:dimensions", - "summaries" - ], - "allOf": [ - { - "$ref": "#/components/schemas/collection" - } - ] - }, - "example": { - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/datacube/v2.2.0/schema.json" - ], - "type": "Collection", - "id": "Sentinel-2", - "title": "Sentinel-2 MSI L2A", - "description": "Sentinel-2A is a wide-swath, high-resolution, multi-spectral imaging mission supporting Copernicus Land Monitoring studies.", - "license": "proprietary", - "keywords": [ - "copernicus", - "esa", - "msi", - "sentinel" - ], - "providers": [ - { - "name": "European Space Agency (ESA)", - "roles": [ - "producer", - "licensor" - ], - "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" - }, - { - "name": "Google", - "roles": [ - "host" - ], - "url": "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2" - } - ], - "extent": { - "spatial": { - "bbox": [ - [ - -180, - -56, - 180, - 83 - ] - ] - }, - "temporal": { - "interval": [ - [ - "2015-06-23T00:00:00Z", - null - ] - ] - } - }, - "links": [ - { - "rel": "license", - "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf", - "type": "application/pdf" - }, - { - "rel": "http://www.opengis.net/def/rel/ogc/1.0/queryables", - "href": "https://openeo.example/api/v1/collections/Sentinel-2A/queryables", - "type": "application/schema+json" - }, - { - "rel": "about", - "href": "https://earth.esa.int/web/sentinel/user-guides/sentinel-2-msi/product-types/level-1c", - "type": "text/html", - "title": "ESA Sentinel-2 MSI Level-1C User Guide" - }, - { - "rel": "example", - "href": "https://openeo.example/api/v1/collections/Sentinel-2/examples/true-color.json", - "type": "application/json", - "title": "Example Process for True-Color Visualization" - }, - { - "rel": "example", - "href": "https://openeo.example/api/v1/collections/Sentinel-2/examples/ndvi.json", - "type": "application/json", - "title": "Example Process for NDVI Calculation and Visualization" - } - ], - "cube:dimensions": { - "x": { - "type": "spatial", - "axis": "x", - "extent": [ - -180, - 180 - ], - "reference_system": 4326 - }, - "y": { - "type": "spatial", - "axis": "y", - "extent": [ - -56, - 83 - ], - "reference_system": 4326 - }, - "t": { - "type": "temporal", - "extent": [ - "2015-06-23T00:00:00Z", - null - ], - "step": null - }, - "bands": { - "type": "bands", - "values": [ - "B1", - "B2", - "B3", - "B4", - "B5", - "B6", - "B7", - "B8", - "B8A", - "B9", - "B10", - "B11", - "B12" - ] - } - }, - "summaries": { - "constellation": [ - "Sentinel-2" - ], - "platform": [ - "Sentinel-2A", - "Sentinel-2B" - ], - "instruments": [ - "MSI" - ], - "eo:cloud_cover": { - "minimum": 0, - "maximum": 75 - }, - "sat:orbit_state": [ - "ascending", - "descending" - ], - "gsd": [ - 10, - 20, - 60 - ], - "eo:bands": [ - { - "name": "B1", - "common_name": "coastal", - "center_wavelength": 0.4439, - "gsd": 60 - }, - { - "name": "B2", - "common_name": "blue", - "center_wavelength": 0.4966, - "gsd": 10 - }, - { - "name": "B3", - "common_name": "green", - "center_wavelength": 0.56, - "gsd": 10 - }, - { - "name": "B4", - "common_name": "red", - "center_wavelength": 0.6645, - "gsd": 10 - }, - { - "name": "B5", - "center_wavelength": 0.7039, - "gsd": 20 - }, - { - "name": "B6", - "center_wavelength": 0.7402, - "gsd": 20 - }, - { - "name": "B7", - "center_wavelength": 0.7825, - "gsd": 20 - }, - { - "name": "B8", - "common_name": "nir", - "center_wavelength": 0.8351, - "gsd": 10 - }, - { - "name": "B8A", - "common_name": "nir08", - "center_wavelength": 0.8648, - "gsd": 20 - }, - { - "name": "B9", - "common_name": "nir09", - "center_wavelength": 0.945, - "gsd": 60 - }, - { - "name": "B10", - "common_name": "cirrus", - "center_wavelength": 1.3735, - "gsd": 60 - }, - { - "name": "B11", - "common_name": "swir16", - "center_wavelength": 1.6137, - "gsd": 20 - }, - { - "name": "B12", - "common_name": "swir22", - "center_wavelength": 2.2024, - "gsd": 20 - } - ], - "proj:epsg": { - "minimum": 32601, - "maximum": 32660 - } - }, - "assets": { - "thumbnail": { - "href": "https://openeo.example/api/v1/collections/Sentinel-2/thumbnail.png", - "type": "image/png", - "title": "Preview", - "roles": [ - "thumbnail" - ] - }, - "inspire": { - "href": "https://openeo.example/api/v1/collections/Sentinel-2/inspire.xml", - "type": "application/xml", - "title": "INSPIRE metadata", - "description": "INSPIRE compliant XML metadata", - "roles": [ - "metadata" - ] - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } + } + } + }, + "/file_formats": { + "get": { + "summary": "Supported file formats", + "operationId": "list-file-types", + "description": "Lists supported input and output file formats.\n*Input* file formats specify which file a back-end can *read* from.\n*Output* file formats specify which file a back-end can *write* to.\n\nThe response to this request is an object listing all available input\nand output file formats separately with their parameters and additional\ndata. This endpoint does not include the supported secondary web\nservices.\n\n**Note**: Format names and parameters MUST be fully aligned with the\nGDAL codes if available, see [GDAL Raster\nFormats](https://gdal.org/drivers/raster/index.html) and [OGR Vector\nFormats](https://gdal.org/drivers/vector/index.html). It is OPTIONAL to\nsupport all output format parameters supported by GDAL. Some file\nformats not available through GDAL may be defined centrally for openEO.\nCustom file formats or parameters MAY be defined.\n\nThe format descriptions must describe how the file formats relate to \ndata cubes. Input file formats must describe how the files have to be\nstructured to be transformed into data cubes. Output file formats must\ndescribe how the data cubes are stored at the back-end and how the \nresulting file structure looks like.\n\nBack-ends MUST NOT support aliases, for example it is not allowed to\nsupport `geotiff` instead of `gtiff`. Nevertheless, openEO Clients MAY\ntranslate user input input for convenience (e.g. translate `geotiff` to\n`gtiff`). Also, for a better user experience the back-end can specify a\n`title`.\n\nFormat names MUST be accepted in a *case insensitive* manner throughout the API.", + "tags": [ + "Capabilities", + "Data Processing" + ], + "security": [ + {}, + { + "Bearer": [] } - }, - "/collections/{collection_id}/queryables": { - "get": { - "summary": "Metadata filters for a specific dataset", - "operationId": "list-collection-queryables", - "description": "Lists **all** supported metadata filters (also called \"queryables\") for\na specific collection.\n\nThis endpoint is compatible with endpoint defined in the STAC API extension\n[`filter`](https://github.com/stac-api-extensions/filter#queryables) and\n[OGC API - Features - Part 3: Filtering](https://github.com/opengeospatial/ogcapi-features/tree/master/extensions/filtering).\nFor a precise definition please follow those specifications.\n\nThis endpoints provides a JSON Schema for each queryable that openEO\nusers can use in multiple scenarios:\n1. For loading data from the collection, e.g. in the process `load_collection`.\n2. For filtering items using CQL2 on the `/collections/{collection_id}/items` endpoint\n (if [STAC API - Features is implemented in addition to the openEO API](#tag/EO-Data-Discovery/STAC)).\n\nNote: Providing the Bearer token is REQUIRED for private collections.", - "tags": [ - "EO Data Discovery" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/collection_id" - } - ], - "responses": { - "200": { - "description": "A JSON Schema defining the queryables.\n\nIt is RECOMMENDED to dereference all \"$refs\".", - "content": { - "application/schema+json": { - "schema": { - "$ref": "#/components/schemas/json_schema" - }, - "example": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://openeo.example/api/v1/collections/Sentinel-2A/queryables", - "type": "object", - "title": "Sentinel 2A", - "properties": { - "eo:cloud_cover": { - "title": "Cloud Cover", - "type": "number", - "minimum": 0, - "maximum": 100 - }, - "platform": { - "title": "Platform", - "description": "The satellite platform.", - "type": "string", - "enum": [ - "sentinel-2a", - "sentinel-2b" - ] - } - }, - "additionalProperties": false - } - } + ], + "responses": { + "200": { + "description": "An object with containing all input and output format separately. For each property `input` and `output` an object is defined where the file format names are the property keys and the property values are objects that define a title, supported parameters and related links.", + "content": { + "application/json": { + "schema": { + "title": "File Formats", + "type": "object", + "required": [ + "input", + "output" + ], + "properties": { + "input": { + "title": "Input File Formats", + "type": "object", + "description": "Map of supported input file formats, i.e. file formats a back-end can **read** from. The property keys are the file format names that are used by clients and users, for example in process graphs.", + "additionalProperties": { + "$ref": "#/components/schemas/file_format" } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/processes": { - "get": { - "summary": "Supported predefined processes", - "operationId": "list-processes", - "description": "Lists all predefined processes and returns detailed process descriptions, including parameters and return values.", - "tags": [ - "Process Discovery" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Formal specification describing the supported predefined processes.", - "content": { - "application/json": { - "schema": { - "title": "Processes", - "type": "object", - "required": [ - "processes", - "links" - ], - "properties": { - "processes": { - "type": "array", - "items": { - "title": "Predefined Process", - "description": "A predefined process made available by the back-end.", - "type": "object", - "required": [ - "id", - "description", - "parameters", - "returns" - ], - "allOf": [ - { - "$ref": "#/components/schemas/process" - } - ] - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - }, - "example": { - "processes": [ - { - "id": "apply", - "summary": "Apply a process to each pixel", - "description": "Applies a *unary* process to each pixel value in the data cube (i.e. a local operation). A unary process takes a single value and returns a single value, for example ``abs()`` or ``linear_scale_range()``.", - "categories": [ - "cubes" - ], - "parameters": [ - { - "name": "data", - "description": "A data cube.", - "schema": { - "type": "object", - "subtype": "datacube" - } - }, - { - "name": "process", - "description": "A unary process to be applied on each value, may consist of multiple sub-processes.", - "schema": { - "type": "object", - "subtype": "process-graph", - "parameters": [ - { - "name": "x", - "description": "The value to process.", - "schema": { - "description": "Any data type." - } - } - ] - } - } - ], - "returns": { - "description": "A data cube with the newly computed values. The resolution, cardinality and the number of dimensions are the same as for the original data cube.", - "schema": { - "type": "object", - "subtype": "datacube" - } - } - }, - { - "id": "multiply", - "summary": "Multiplication of two numbers", - "description": "Multiplies the two numbers `x` and `y` (*x * y*) and returns the computed product.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", - "categories": [ - "math" - ], - "parameters": [ - { - "name": "x", - "description": "The multiplier.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - { - "name": "y", - "description": "The multiplicand.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The computed product of the two numbers.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "exceptions": { - "MultiplicandMissing": { - "message": "Multiplication requires at least two numbers." - } - }, - "examples": [ - { - "arguments": { - "x": 5, - "y": 2.5 - }, - "returns": 12.5 - }, - { - "arguments": { - "x": -2, - "y": -4 - }, - "returns": 8 - }, - { - "arguments": { - "x": 1, - "y": null - }, - "returns": null - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/Product.html", - "title": "Product explained by Wolfram MathWorld" - }, - { - "rel": "about", - "href": "https://ieeexplore.ieee.org/document/8766229", - "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" - } - ] - } - ], - "links": [ - { - "rel": "alternate", - "href": "https://openeo.example/processes", - "type": "text/html", - "title": "HTML version of the processes" - } - ] - } - } + }, + "output": { + "title": "Output File Formats", + "type": "object", + "description": "Map of supported output file formats, i.e. file formats a back-end can **write** to. The property keys are the file format names that are used by clients and users, for example in process graphs.", + "additionalProperties": { + "$ref": "#/components/schemas/file_format" } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + } + } + }, + "example": { + "output": { + "GTiff": { + "title": "GeoTiff", + "description": "Export to GeoTiff. Doesn't support cloud-optimized GeoTiffs (COGs) yet.", + "gis_data_types": [ + "raster" + ], + "parameters": { + "tiled": { + "type": "boolean", + "description": "This option can be used to force creation of tiled TIFF files [true]. By default [false] stripped TIFF files are created.", + "default": false + }, + "compress": { + "type": "string", + "description": "Set the compression to use.", + "default": "NONE", + "enum": [ + "JPEG", + "LZW", + "DEFLATE", + "NONE" + ] + }, + "jpeg_quality": { + "type": "integer", + "description": "Set the JPEG quality when using JPEG.", + "minimum": 1, + "maximum": 100, + "default": 75 + } + }, + "links": [ + { + "href": "https://gdal.org/drivers/raster/gtiff.html", + "rel": "about", + "title": "GDAL on the GeoTiff file format and storage options" + } + ] + }, + "GPKG": { + "title": "OGC GeoPackage", + "gis_data_types": [ + "raster", + "vector" + ], + "parameters": { + "version": { + "type": "string", + "description": "Set GeoPackage version. In AUTO mode, this will be equivalent to 1.2 starting with GDAL 2.3.", + "enum": [ + "auto", + "1", + "1.1", + "1.2" + ], + "default": "auto" + } + }, + "links": [ + { + "href": "https://gdal.org/drivers/raster/gpkg.html", + "rel": "about", + "title": "GDAL on GeoPackage for raster data" + }, + { + "href": "https://gdal.org/drivers/vector/gpkg.html", + "rel": "about", + "title": "GDAL on GeoPackage for vector data" + } + ] + } + }, + "input": { + "GPKG": { + "title": "OGC GeoPackage", + "gis_data_types": [ + "raster", + "vector" + ], + "parameters": { + "table": { + "type": "string", + "description": "**RASTER ONLY.** Name of the table containing the tiles. If the GeoPackage dataset only contains one table, this option is not necessary. Otherwise, it is required." + } + }, + "links": [ + { + "href": "https://gdal.org/drivers/raster/gpkg.html", + "rel": "about", + "title": "GDAL on GeoPackage for raster data" + }, + { + "href": "https://gdal.org/drivers/vector/gpkg.html", + "rel": "about", + "title": "GDAL on GeoPackage for vector data" + } + ] + } } + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/udf_runtimes": { - "get": { - "summary": "Supported UDF runtimes", - "operationId": "list-udf-runtimes", - "description": "Lists the supported runtimes for user-defined functions (UDFs), which includes either the programming languages including version numbers and available libraries including version numbers or docker containers.", - "tags": [ - "Capabilities" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Description of UDF runtime support", - "content": { - "application/json": { - "schema": { - "title": "UDF Runtimes", - "type": "object", - "description": "Map of available runtime environments. Runtime environments\ncan be either a programming language environment or Docker-based.\n\nEach runtime environment has a unique name, which is used as\nthe property key. The name is used in processes to select the\nruntime environment for UDFs, so the names should be stable and\nmeaningful.\nIt is RECOMMENDED to use the following naming and casing:\n* For programming langauge environments use the names as provided\n in in the [Scriptol List of Programming Languages](https://www.scriptol.com/programming/list-programming-languages.php).\n* For docker images use the docker image identifier excluding the registry path.", - "additionalProperties": { - "x-additionalPropertiesName": "UDF Runtime name", - "allOf": [ - { - "$ref": "#/components/schemas/udf_runtime" - } - ] - } - }, - "example": { - "PHP": { - "title": "PHP v7.x", - "description": "Just an example how to reference a docker image.", - "experimental": true, - "type": "docker", - "docker": "openeo/udf-php7", - "default": "latest", - "tags": [ - "latest", - "7.3.1", - "7.3", - "7.2" - ], - "links": [ - { - "href": "https://hub.docker.com/openeo/udf-php7/", - "rel": "about" - } - ] - }, - "R": { - "title": "R v3.x for Statistical Computing", - "description": "R programming language with `Rcpp` and `rmarkdown` extensions installed.", - "type": "language", - "default": "3.5.2", - "versions": { - "3.1.0": { - "deprecated": true, - "libraries": { - "Rcpp": { - "version": "1.0.10", - "links": [ - { - "href": "https://cran.r-project.org/web/packages/Rcpp/index.html", - "rel": "about" - } - ] - }, - "rmarkdown": { - "version": "1.7.0", - "links": [ - { - "href": "https://cran.r-project.org/web/packages/rmarkdown/index.html", - "rel": "about" - } - ] - } - } - }, - "3.5.2": { - "libraries": { - "Rcpp": { - "version": "1.2.0", - "links": [ - { - "href": "https://cran.r-project.org/web/packages/Rcpp/index.html", - "rel": "about" - } - ] - }, - "rmarkdown": { - "version": "1.7.0", - "links": [ - { - "href": "https://cran.r-project.org/web/packages/rmarkdown/index.html", - "rel": "about" - } - ] - } - } - } - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + } + } + }, + "/conformance": { + "get": { + "summary": "Conformance classes this API implements", + "operationId": "conformance", + "description": "Lists all conformance classes specified in various standards that the\nimplementation conforms to. Conformance classes are commonly used in\nall OGC APIs and the STAC API specification. openEO adds relatively\nbroadly defined conformance classes, especially for the extensions.\nOtherwise, the implemented functionality can usually be retrieved from\nthe [capabilties](#tag/Capabilities/operation/capabilities) in openEO.\n\nThe general openEO conformance class is `https://api.openeo.org/1.2.0`.\nSee the individual openEO API extensions for their conformance classes.\n\nThe conformance classes listed at this endpoint and listed in the \ncorresponding `conformsTo` property in `GET /` MUST be equal.\n\nMore details:\n- [STAC API](https://github.com/radiantearth/stac-api-spec), especially the conformance class \"STAC API - Collections\"\n- [OGC APIs](https://ogcapi.ogc.org/)", + "tags": [ + "Capabilities" + ], + "responses": { + "200": { + "description": "The URIs of all conformance classes supported by the server.", + "content": { + "application/json": { + "schema": { + "title": "OGC Conformance Classes", + "type": "object", + "required": [ + "conformsTo" + ], + "properties": { + "conformsTo": { + "$ref": "#/components/schemas/conformsTo" + } } + } } + } + }, + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/credentials/oidc": { - "get": { - "summary": "OpenID Connect authentication", - "operationId": "authenticate-oidc", - "description": "Lists the supported [OpenID Connect](http://openid.net/connect/)\nproviders (OP). OpenID Connect Providers MUST support [OpenID Connect\nDiscovery](http://openid.net/specs/openid-connect-discovery-1_0.html).\n\nIt is highly RECOMMENDED to implement OpenID Connect for public services\nin favor of Basic authentication.\n\nopenEO clients MUST use the **access token** as part of the Bearer token\nfor authorization in subsequent API calls (see also the information\nabout Bearer tokens in this document). Clients MUST NOT use the id token\nor the authorization code. The access token provided by an OpenID Connect\nProvider does not necessarily provide information about the issuer (i.e. the\nOpenID Connect provider) and therefore a prefix MUST be added to the Bearer\nToken sent in subsequent API calls to protected endpoints. The Bearer\nToken sent to protected endpoints MUST consist of the authentication\nmethod (here `oidc`), the provider ID and the access token itself. All\nseparated by a forward slash `/`. The provider ID corresponds to the\nvalue specified for `id` for each provider in the response body of this\nendpoint. The header in subsequent API calls for a provider with `id`\n`ms` would look as follows: `Authorization: Bearer oidc/ms/TOKEN`\n(replace `TOKEN` with the actual access token received from the OpenID\nConnect Provider).\n\nBack-ends MAY request user information ([including Claims](https://openid.net/specs/openid-connect-core-1_0.html#Claims))\nfrom the [OpenID Connect Userinfo endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)\nusing the access token (without the prefix described above). Therefore,\nboth openEO client and openEO back-end are relying parties (clients) to\nthe OpenID Connect Provider.", - "tags": [ - "Account Management" - ], - "security": [ - {} - ], - "responses": { - "200": { - "description": "Lists the the OpenID Connect Providers.", - "content": { - "application/json": { - "schema": { - "title": "OpenID Connect Providers", - "type": "object", - "required": [ - "providers" - ], - "properties": { - "providers": { - "type": "array", - "description": "The first provider in this list is the default provider for authentication. Clients can either pre-select or directly use the default provider for authentication if the user doesn't specify a specific value.", - "minItems": 1, - "items": { - "title": "OpenID Connect Provider", - "type": "object", - "required": [ - "id", - "issuer", - "title" - ], - "properties": { - "id": { - "type": "string", - "description": "A per-backend **unique** identifier for the OpenID Connect Provider to be as prefix for the Bearer token.", - "pattern": "[\\d\\w]{1,20}" - }, - "issuer": { - "type": "string", - "format": "uri", - "description": "The [issuer location](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig) (also referred to as 'authority' in some client libraries) is the URL of the OpenID Connect provider, which conforms to a set of rules:\n1. After appending `/.well-known/openid-configuration` to the URL, a [HTTP/1.1 GET request](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest) to the concatenated URL MUST return a [OpenID Connect Discovery Configuration Response](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). The response provides all information required to authenticate using OpenID Connect.\n2. The URL MUST NOT contain a terminating forward slash `/`.", - "example": "https://accounts.google.com" - }, - "scopes": { - "type": "array", - "description": "A list of OpenID Connect scopes that the client MUST at least include when requesting authorization. Clients MAY add additional scopes such as the `offline_access` scope to retrieve a refresh token.\nIf scopes are specified, the list MUST at least contain the `openid` scope.", - "items": { - "type": "string" - } - }, - "title": { - "type": "string", - "description": "The name that is publicly shown in clients for this OpenID Connect provider." - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "A description that explains how the authentication procedure works.\n\nIt should make clear how to register and get credentials. This should\ninclude instruction on setting up `client_id`, `client_secret` and `redirect_uri`.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich\ntext representation." - }, - "default_clients": { - "title": "Default OpenID Connect Clients", - "type": "array", - "description": "List of default OpenID Connect clients that can be used by an openEO client\nfor OpenID Connect based authentication.\n\nA default OpenID Connect client is managed by the back-end implementer.\nIt MUST be configured to be usable without a client secret,\nwhich limits its applicability to OpenID Connect grant types like\n\"Authorization Code Grant with PKCE\" and \"Device Authorization Grant with PKCE\"\n\nA default OpenID Connect client is provided without availability guarantees.\nThe back-end implementer CAN revoke, reset or update it any time.\nAs such, openEO clients SHOULD NOT store or cache default OpenID Connect client information\nfor long term usage.\nA default OpenID Connect client is intended to simplify authentication for novice users.\nFor production use cases, it is RECOMMENDED to set up a dedicated OpenID Connect client.", - "uniqueItems": true, - "items": { - "title": "Default OpenID Connect Client", - "type": "object", - "required": [ - "id", - "grant_types" - ], - "properties": { - "id": { - "type": "string", - "description": "The OpenID Connect Client ID to be used in the authentication procedure." - }, - "grant_types": { - "type": "array", - "description": "List of authorization grant types (flows) supported by the OpenID Connect client.\nA grant type descriptor consist of a OAuth 2.0 grant type,\nwith an additional `+pkce` suffix when the grant type should be used with\nthe PKCE extension as defined in [RFC 7636](https://www.rfc-editor.org/rfc/rfc7636.html).\n\nAllowed values:\n- `implicit`: Implicit Grant as specified in [RFC 6749, sec. 1.3.2](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.3.2)\n- `authorization_code` / `authorization_code+pkce`: Authorization Code Grant as specified in [RFC 6749, sec. 1.3.1](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.3.1), with or without PKCE extension.\n- `urn:ietf:params:oauth:grant-type:device_code` / `urn:ietf:params:oauth:grant-type:device_code+pkce`: Device Authorization Grant (aka Device Code Flow) as specified in [RFC 8628](https://www.rfc-editor.org/rfc/rfc8628.html), with or without PKCE extension. Note that the combination of this grant with the PKCE extension is *not standardized* yet.\n- `refresh_token`: Refresh Token as specified in [RFC 6749, sec. 1.5](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.5)", - "minItems": 1, - "uniqueItems": true, - "items": { - "type": "string", - "enum": [ - "implicit", - "authorization_code", - "authorization_code+pkce", - "urn:ietf:params:oauth:grant-type:device_code", - "urn:ietf:params:oauth:grant-type:device_code+pkce", - "refresh_token" - ] - } - }, - "redirect_urls": { - "type": "array", - "description": "List of redirect URLs that are whitelisted by the OpenID Connect client.\nRedirect URLs MUST be provided when the OpenID Connect client supports\nthe Implicit Grant or the Authorization Code Grant (with or without PKCE extension).", - "uniqueItems": true, - "items": { - "type": "string", - "format": "uri" - } - } - } - } - }, - "links": { - "type": "array", - "description": "Links related to this provider, for example a\nhelp page or a page to register a new user account.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - } - } - } - } - } - }, - "example": { - "providers": [ - { - "id": "egi", - "issuer": "https://aai.egi.eu/oidc", - "title": "EGI (default)", - "description": "Login with your academic account.", - "scopes": [ - "openid", - "profile", - "email" - ], - "default_clients": [ - { - "id": "KStcUzD5AIUA", - "grant_types": [ - "implicit", - "authorization_code+pkce", - "urn:ietf:params:oauth:grant-type:device_code+pkce", - "refresh_token" - ], - "redirect_urls": [ - "https://editor.openeo.org/" - ] - } - ] - }, - { - "id": "google", - "issuer": "https://accounts.google.com", - "title": "Google", - "description": "Login with your Google Account.", - "scopes": [ - "openid", - "profile", - "email", - "earthengine" - ] - }, - { - "id": "ms", - "issuer": "https://login.microsoftonline.com/example-tenant/v2.0", - "title": "Microsoft", - "description": "Login with your Microsoft or Skype Account.", - "scopes": [] - } - ] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } + } + } + }, + "/collections": { + "get": { + "summary": "Basic metadata for all datasets", + "operationId": "list-collections", + "description": "Lists available collections with at least the required information.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting larger optional values from the objects in `collections` (e.g. the\n`summaries` and `cube:dimensions` properties).\nTo get the full metadata for a collection clients MUST\nrequest `GET /collections/{collection_id}`.\n\nThis endpoint is compatible with [STAC API 0.9.0 and later](https://stacspec.org) and\n[OGC API - Features 1.0](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html).\n[STAC API extensions](https://stac-api-extensions.github.io) and\n[STAC extensions](https://stac-extensions.github.io)\ncan be implemented in addition to what is documented here.\n\nNote: Although it is possible to request public collections without\nauthorization, it is RECOMMENDED that clients (re-)request the collections\nwith the Bearer token once available to also retrieve any private collections.", + "tags": [ + "EO Data Discovery" + ], + "security": [ + {}, + { + "Bearer": [] } - }, - "/credentials/basic": { - "get": { - "summary": "HTTP Basic authentication", - "operationId": "authenticate-basic", - "description": "Checks the credentials provided through [HTTP Basic Authentication according to RFC 7617](https://www.rfc-editor.org/rfc/rfc7617.html) and returns an access token for valid credentials.\n\nThe credentials (username and password) MUST be sent in the HTTP header `Authorization` with type `Basic` and the Base64 encoded string consisting of username and password separated by a double colon `:`. The header would look as follows for username `user` and password `pw`: `Authorization: Basic dXNlcjpwdw==`.\n\nThe access token has to be used in the Bearer token for authorization in subsequent API calls (see also the information about Bearer tokens in this document). The access token returned by this request MUST NOT be provided with `basic//` prefix, but the Bearer Token sent in subsequent API calls to protected endpoints MUST be prefixed with `basic//`. The header in subsequent API calls would look as follows: `Authorization: Bearer basic//TOKEN` (replace `TOKEN` with the actual access token).\n\nIt is RECOMMENDED to implement this authentication method for non-public services only.", - "tags": [ - "Account Management" - ], - "security": [ - { - "Basic": [] - } - ], - "responses": { - "200": { - "description": "Credentials are correct and authentication succeeded.", - "content": { - "application/json": { - "schema": { - "title": "HTTP Basic Access Token", - "type": "object", - "required": [ - "access_token" - ], - "properties": { - "access_token": { - "description": "The access token (without `basic//` prefix) to be used in the Bearer token for authorization in subsequent API calls.", - "type": "string", - "example": "b34ba2bdf9ac9ee1" - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" } - }, - "/validation": { - "post": { - "summary": "Validate a user-defined process (graph)", - "operationId": "validate-custom-process", - "description": "Validates a user-defined process without executing it. A user-defined process is\nconsidered valid unless the `errors` array in the response contains at\nleast one error.\n\nChecks whether the process graph is schematically correct and the\nprocesses are supported by the back-end. It MUST also check the\narguments against the schema, but checking whether the arguments are\nadequate in the context of data is OPTIONAL. For example, a non-existing\nband name may get rejected only by a few back-ends.\nThe validation MUST NOT throw an error for unresolvable process parameters.\n\nBack-ends MUST validate the process graph. Validating the corresponding\nmetadata is OPTIONAL.\n\nErrors that usually occur during processing MAY NOT get reported, e.g.\nif a referenced file is accessible at the time of execution.\n\nBack-ends can either report all errors at once or stop the validation\nonce they found the first error. \n\nPlease note that a validation always returns with HTTP status code 200.\nError codes in the 4xx and 5xx ranges MUST be returned only when the\ngeneral validation request is invalid (e.g. server is busy or properties\nin the request body are missing), but never if an error was found during\nvalidation of the user-defined process (e.g. an unsupported process).", - "tags": [ - "Data Processing", - "User-Defined Processes" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Returns the validation result as a list of errors. An empty list indicates a successful validation.", - "content": { - "application/json": { - "schema": { - "title": "Validation Result", - "type": "object", - "required": [ - "errors" - ], - "properties": { - "errors": { - "description": "A list of validation errors.", - "type": "array", - "items": { - "$ref": "#/components/schemas/error" - } - } - } - } - } + ], + "responses": { + "200": { + "description": "Lists of collections and related links.", + "content": { + "application/json": { + "schema": { + "title": "Collections", + "type": "object", + "required": [ + "collections", + "links" + ], + "properties": { + "collections": { + "type": "array", + "items": { + "$ref": "#/components/schemas/collection" } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + }, + "example": { + "collections": [ + { + "stac_version": "1.0.0", + "type": "Collection", + "id": "Sentinel-2A", + "title": "Sentinel-2A MSI L1C", + "description": "Sentinel-2A is a wide-swath, high-resolution, multi-spectral imaging mission supporting Copernicus Land Monitoring studies, including the monitoring of vegetation, soil and water cover, as well as observation of inland waterways and coastal areas.", + "license": "proprietary", + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -56, + 180, + 83 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2015-06-23T00:00:00Z", + "2019-01-01T00:00:00Z" + ] + ] + } + }, + "keywords": [ + "copernicus", + "esa", + "msi", + "sentinel" + ], + "providers": [ + { + "name": "European Space Agency (ESA)", + "roles": [ + "producer", + "licensor" + ], + "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" + }, + { + "name": "openEO", + "roles": [ + "host" + ], + "url": "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2" + } + ], + "links": [ + { + "rel": "license", + "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf" + } + ] + }, + { + "stac_version": "1.0.0", + "type": "Collection", + "id": "MOD09Q1", + "title": "MODIS/Terra Surface Reflectance 8-Day L3 Global 250m SIN Grid V006", + "description": "The MOD09Q1 Version 6 product provides an estimate of the surface spectral reflectance of Terra MODIS Bands 1-2 corrected for atmospheric conditions such as gasses, aerosols, and Rayleigh scattering. Provided along with the two 250 m MODIS bands is one additional layer, the Surface Reflectance QC 250 m band. For each pixel, a value is selected from all the acquisitions within the 8-day composite period. The criteria for the pixel choice include cloud and solar zenith. When several acquisitions meet the criteria the pixel with the minimum channel 3 (blue) value is used. Validation at stage 3 has been achieved for all MODIS Surface Reflectance products.", + "license": "proprietary", + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -90, + 180, + 90 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2000-02-01T00:00:00Z", + null + ] + ] + } + }, + "links": [ + { + "rel": "license", + "href": "https://openeo.example/api/v1/collections/MOD09Q1/license" + } + ] + } + ], + "links": [ + { + "rel": "alternate", + "href": "https://openeo.example/csw", + "title": "openEO catalog (OGC Catalogue Services 3.0)" + } + ] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/collections/{collection_id}": { + "get": { + "summary": "Full metadata for a specific dataset", + "operationId": "describe-collection", + "description": "Lists **all** information about a specific collection specified by the\nidentifier `collection_id`.\n\nThis endpoint is compatible with [STAC API 0.9.0 and later](https://stacspec.org) and\n[OGC API - Features 1.0](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html).\n[STAC API extensions](https://stac-api-extensions.github.io) and\n[STAC extensions](https://stac-extensions.github.io)\ncan be implemented in addition to what is documented here.\n\nNote: Providing the Bearer token is REQUIRED for private collections.", + "tags": [ + "EO Data Discovery" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/collection_id" + } + ], + "responses": { + "200": { + "description": "JSON object with the full collection metadata.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "cube:dimensions", + "summaries" + ], + "allOf": [ + { + "$ref": "#/components/schemas/collection" + } + ] + }, + "example": { + "stac_version": "1.0.0", + "stac_extensions": [ + "https://stac-extensions.github.io/datacube/v2.2.0/schema.json" + ], + "type": "Collection", + "id": "Sentinel-2", + "title": "Sentinel-2 MSI L2A", + "description": "Sentinel-2A is a wide-swath, high-resolution, multi-spectral imaging mission supporting Copernicus Land Monitoring studies.", + "license": "proprietary", + "keywords": [ + "copernicus", + "esa", + "msi", + "sentinel" + ], + "providers": [ + { + "name": "European Space Agency (ESA)", + "roles": [ + "producer", + "licensor" + ], + "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" + }, + { + "name": "Google", + "roles": [ + "host" + ], + "url": "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2" + } + ], + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -56, + 180, + 83 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2015-06-23T00:00:00Z", + null + ] + ] + } + }, + "links": [ + { + "rel": "license", + "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf", + "type": "application/pdf" + }, + { + "rel": "http://www.opengis.net/def/rel/ogc/1.0/queryables", + "href": "https://openeo.example/api/v1/collections/Sentinel-2A/queryables", + "type": "application/schema+json" + }, + { + "rel": "about", + "href": "https://earth.esa.int/web/sentinel/user-guides/sentinel-2-msi/product-types/level-1c", + "type": "text/html", + "title": "ESA Sentinel-2 MSI Level-1C User Guide" + }, + { + "rel": "example", + "href": "https://openeo.example/api/v1/collections/Sentinel-2/examples/true-color.json", + "type": "application/json", + "title": "Example Process for True-Color Visualization" + }, + { + "rel": "example", + "href": "https://openeo.example/api/v1/collections/Sentinel-2/examples/ndvi.json", + "type": "application/json", + "title": "Example Process for NDVI Calculation and Visualization" + } + ], + "cube:dimensions": { + "x": { + "type": "spatial", + "axis": "x", + "extent": [ + -180, + 180 + ], + "reference_system": 4326 + }, + "y": { + "type": "spatial", + "axis": "y", + "extent": [ + -56, + 83 + ], + "reference_system": 4326 + }, + "t": { + "type": "temporal", + "extent": [ + "2015-06-23T00:00:00Z", + null + ], + "step": null + }, + "bands": { + "type": "bands", + "values": [ + "B1", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B8A", + "B9", + "B10", + "B11", + "B12" + ] + } }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "summaries": { + "constellation": [ + "Sentinel-2" + ], + "platform": [ + "Sentinel-2A", + "Sentinel-2B" + ], + "instruments": [ + "MSI" + ], + "eo:cloud_cover": { + "minimum": 0, + "maximum": 75 + }, + "sat:orbit_state": [ + "ascending", + "descending" + ], + "gsd": [ + 10, + 20, + 60 + ], + "eo:bands": [ + { + "name": "B1", + "common_name": "coastal", + "center_wavelength": 0.4439, + "gsd": 60 + }, + { + "name": "B2", + "common_name": "blue", + "center_wavelength": 0.4966, + "gsd": 10 + }, + { + "name": "B3", + "common_name": "green", + "center_wavelength": 0.56, + "gsd": 10 + }, + { + "name": "B4", + "common_name": "red", + "center_wavelength": 0.6645, + "gsd": 10 + }, + { + "name": "B5", + "center_wavelength": 0.7039, + "gsd": 20 + }, + { + "name": "B6", + "center_wavelength": 0.7402, + "gsd": 20 + }, + { + "name": "B7", + "center_wavelength": 0.7825, + "gsd": 20 + }, + { + "name": "B8", + "common_name": "nir", + "center_wavelength": 0.8351, + "gsd": 10 + }, + { + "name": "B8A", + "common_name": "nir08", + "center_wavelength": 0.8648, + "gsd": 20 + }, + { + "name": "B9", + "common_name": "nir09", + "center_wavelength": 0.945, + "gsd": 60 + }, + { + "name": "B10", + "common_name": "cirrus", + "center_wavelength": 1.3735, + "gsd": 60 + }, + { + "name": "B11", + "common_name": "swir16", + "center_wavelength": 1.6137, + "gsd": 20 + }, + { + "name": "B12", + "common_name": "swir22", + "center_wavelength": 2.2024, + "gsd": 20 + } + ], + "proj:epsg": { + "minimum": 32601, + "maximum": 32660 + } }, - "5XX": { - "$ref": "#/components/responses/server_error" + "assets": { + "thumbnail": { + "href": "https://openeo.example/api/v1/collections/Sentinel-2/thumbnail.png", + "type": "image/png", + "title": "Preview", + "roles": [ + "thumbnail" + ] + }, + "inspire": { + "href": "https://openeo.example/api/v1/collections/Sentinel-2/inspire.xml", + "type": "application/xml", + "title": "INSPIRE metadata", + "description": "INSPIRE compliant XML metadata", + "roles": [ + "metadata" + ] + } } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/collections/{collection_id}/queryables": { + "get": { + "summary": "Metadata filters for a specific dataset", + "operationId": "list-collection-queryables", + "description": "Lists **all** supported metadata filters (also called \"queryables\") for\na specific collection.\n\nThis endpoint is compatible with endpoint defined in the STAC API extension\n[`filter`](https://github.com/stac-api-extensions/filter#queryables) and\n[OGC API - Features - Part 3: Filtering](https://github.com/opengeospatial/ogcapi-features/tree/master/extensions/filtering).\nFor a precise definition please follow those specifications.\n\nThis endpoints provides a JSON Schema for each queryable that openEO\nusers can use in multiple scenarios:\n1. For loading data from the collection, e.g. in the process `load_collection`.\n2. For filtering items using CQL2 on the `/collections/{collection_id}/items` endpoint\n (if [STAC API - Features is implemented in addition to the openEO API](#tag/EO-Data-Discovery/STAC)).\n\nNote: Providing the Bearer token is REQUIRED for private collections.", + "tags": [ + "EO Data Discovery" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/collection_id" + } + ], + "responses": { + "200": { + "description": "A JSON Schema defining the queryables.\n\nIt is RECOMMENDED to dereference all \"$refs\".", + "content": { + "application/schema+json": { + "schema": { + "$ref": "#/components/schemas/json_schema" + }, + "example": { + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://openeo.example/api/v1/collections/Sentinel-2A/queryables", + "type": "object", + "title": "Sentinel 2A", + "properties": { + "eo:cloud_cover": { + "title": "Cloud Cover", + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "platform": { + "title": "Platform", + "description": "The satellite platform.", + "type": "string", + "enum": [ + "sentinel-2a", + "sentinel-2b" + ] + } + }, + "additionalProperties": false + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/processes": { + "get": { + "summary": "Supported predefined processes", + "operationId": "list-processes", + "description": "Lists all predefined processes and returns detailed process descriptions, including parameters and return values.", + "tags": [ + "Process Discovery" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Formal specification describing the supported predefined processes.", + "content": { + "application/json": { + "schema": { + "title": "Processes", + "type": "object", + "required": [ + "processes", + "links" + ], + "properties": { + "processes": { + "type": "array", + "items": { + "title": "Predefined Process", + "description": "A predefined process made available by the back-end.", + "type": "object", + "required": [ + "id", + "description", + "parameters", + "returns" + ], + "allOf": [ + { + "$ref": "#/components/schemas/process" + } + ] + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + }, + "example": { + "processes": [ + { + "id": "apply", + "summary": "Apply a process to each pixel", + "description": "Applies a *unary* process to each pixel value in the data cube (i.e. a local operation). A unary process takes a single value and returns a single value, for example ``abs()`` or ``linear_scale_range()``.", + "categories": [ + "cubes" + ], + "parameters": [ + { + "name": "data", + "description": "A data cube.", "schema": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "examples": { - "evi_user_defined_process": { - "$ref": "#/components/examples/evi_user_defined_process" + "type": "object", + "subtype": "datacube" + } + }, + { + "name": "process", + "description": "A unary process to be applied on each value, may consist of multiple sub-processes.", + "schema": { + "type": "object", + "subtype": "process-graph", + "parameters": [ + { + "name": "x", + "description": "The value to process.", + "schema": { + "description": "Any data type." + } } + ] } + } + ], + "returns": { + "description": "A data cube with the newly computed values. The resolution, cardinality and the number of dimensions are the same as for the original data cube.", + "schema": { + "type": "object", + "subtype": "datacube" + } } - }, - "description": "Specifies the user-defined process to be validated." + }, + { + "id": "multiply", + "summary": "Multiplication of two numbers", + "description": "Multiplies the two numbers `x` and `y` (*x * y*) and returns the computed product.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", + "categories": [ + "math" + ], + "parameters": [ + { + "name": "x", + "description": "The multiplier.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + { + "name": "y", + "description": "The multiplicand.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The computed product of the two numbers.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + "exceptions": { + "MultiplicandMissing": { + "message": "Multiplication requires at least two numbers." + } + }, + "examples": [ + { + "arguments": { + "x": 5, + "y": 2.5 + }, + "returns": 12.5 + }, + { + "arguments": { + "x": -2, + "y": -4 + }, + "returns": 8 + }, + { + "arguments": { + "x": 1, + "y": null + }, + "returns": null + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/Product.html", + "title": "Product explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/8766229", + "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" + } + ] + } + ], + "links": [ + { + "rel": "alternate", + "href": "https://openeo.example/processes", + "type": "text/html", + "title": "HTML version of the processes" + } + ] + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/result": { - "post": { - "summary": "Process and download data synchronously", - "operationId": "compute-result", - "description": "Executes a user-defined process directly (synchronously) and the result will be downloaded in the format specified in the process graph. This endpoint can be used to generate small previews or test user-defined processes before starting a batch job.\nTimeouts on either client- or server-side are to be expected for complex computations. Back-ends MAY send the openEO error `ProcessGraphComplexity` immediately if the computation is expected to time out. Otherwise requests MAY time-out after a certain amount of time by sending openEO error `RequestTimeout`.\nA header named `OpenEO-Costs` MAY be sent with all responses, which MUST include the costs for processing and downloading the data. Additionally, a link to a log file MAY be sent in the header.", - "tags": [ - "Data Processing" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Result data in the requested output format", - "headers": { - "Content-Type": { - "description": "The appropriate media (MIME) type for the requested output\nformat MUST be sent, if the response contains a single file.\n\nTo send multiple files at once it is RECOMMENDED to use the\n[`tar` file format](https://www.gnu.org/software/tar/manual/html_node/Standard.html)\n(media type: `application/x-tar`).\n\nTo mimic the results of batch jobs, it is RECOMMENDED that \n1. clients extract the tar file directly after receiving it so that users\n can directly work on the contained files *and*\n2. back-ends add STAC Items and/or Collections to the tar file\n so that users can make sense of the files.", - "schema": { - "type": "string" + } + } + }, + "/udf_runtimes": { + "get": { + "summary": "Supported UDF runtimes", + "operationId": "list-udf-runtimes", + "description": "Lists the supported runtimes for user-defined functions (UDFs), which includes either the programming languages including version numbers and available libraries including version numbers or docker containers.", + "tags": [ + "Capabilities" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Description of UDF runtime support", + "content": { + "application/json": { + "schema": { + "title": "UDF Runtimes", + "type": "object", + "description": "Map of available runtime environments. Runtime environments\ncan be either a programming language environment or Docker-based.\n\nEach runtime environment has a unique name, which is used as\nthe property key. The name is used in processes to select the\nruntime environment for UDFs, so the names should be stable and\nmeaningful.\nIt is RECOMMENDED to use the following naming and casing:\n* For programming langauge environments use the names as provided\n in in the [Scriptol List of Programming Languages](https://www.scriptol.com/programming/list-programming-languages.php).\n* For docker images use the docker image identifier excluding the registry path.", + "additionalProperties": { + "x-additionalPropertiesName": "UDF Runtime name", + "allOf": [ + { + "$ref": "#/components/schemas/udf_runtime" + } + ] + } + }, + "example": { + "PHP": { + "title": "PHP v7.x", + "description": "Just an example how to reference a docker image.", + "experimental": true, + "type": "docker", + "docker": "openeo/udf-php7", + "default": "latest", + "tags": [ + "latest", + "7.3.1", + "7.3", + "7.2" + ], + "links": [ + { + "href": "https://hub.docker.com/openeo/udf-php7/", + "rel": "about" + } + ] + }, + "R": { + "title": "R v3.x for Statistical Computing", + "description": "R programming language with `Rcpp` and `rmarkdown` extensions installed.", + "type": "language", + "default": "3.5.2", + "versions": { + "3.1.0": { + "deprecated": true, + "libraries": { + "Rcpp": { + "version": "1.0.10", + "links": [ + { + "href": "https://cran.r-project.org/web/packages/Rcpp/index.html", + "rel": "about" } + ] }, - "OpenEO-Costs": { - "description": "MAY include the costs for processing and downloading the data.", - "schema": { - "$ref": "#/components/schemas/money" + "rmarkdown": { + "version": "1.7.0", + "links": [ + { + "href": "https://cran.r-project.org/web/packages/rmarkdown/index.html", + "rel": "about" + } + ] + } + } + }, + "3.5.2": { + "libraries": { + "Rcpp": { + "version": "1.2.0", + "links": [ + { + "href": "https://cran.r-project.org/web/packages/Rcpp/index.html", + "rel": "about" } + ] }, - "Link": { - "description": "The header MAY indicate a link to a log file generated by the request. If provided, the link MUST be serialized according to [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288.html#section-3) and MUST use the relation type `monitor`. The link MUST follow the specifications for the links `GET /jobs/{job_id}/logs` and `GET /services/{service_id}/logs`, except that is MUST NOT accept any parameters (limit/offset). Therefore, the link MUST be accessible with HTTP GET, MUST be secured using a Bearer token and MUST follow the corresponding request body schema.", - "schema": { - "type": "string", - "pattern": "^<[^>]+>;\\s?rel=\"monitor\"", - "example": "; rel=\"monitor\"" + "rmarkdown": { + "version": "1.7.0", + "links": [ + { + "href": "https://cran.r-project.org/web/packages/rmarkdown/index.html", + "rel": "about" } + ] } + } } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + } } - }, - "requestBody": { - "description": "Specifies the job details, e.g. the user-defined process and billing details.", - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Synchronous Result Request", + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/credentials/oidc": { + "get": { + "summary": "OpenID Connect authentication", + "operationId": "authenticate-oidc", + "description": "Lists the supported [OpenID Connect](http://openid.net/connect/)\nproviders (OP). OpenID Connect Providers MUST support [OpenID Connect\nDiscovery](http://openid.net/specs/openid-connect-discovery-1_0.html).\n\nIt is highly RECOMMENDED to implement OpenID Connect for public services\nin favor of Basic authentication.\n\nopenEO clients MUST use the **access token** as part of the Bearer token\nfor authorization in subsequent API calls (see also the information\nabout Bearer tokens in this document). Clients MUST NOT use the id token\nor the authorization code. The access token provided by an OpenID Connect\nProvider does not necessarily provide information about the issuer (i.e. the\nOpenID Connect provider) and therefore a prefix MUST be added to the Bearer\nToken sent in subsequent API calls to protected endpoints. The Bearer\nToken sent to protected endpoints MUST consist of the authentication\nmethod (here `oidc`), the provider ID and the access token itself. All\nseparated by a forward slash `/`. The provider ID corresponds to the\nvalue specified for `id` for each provider in the response body of this\nendpoint. The header in subsequent API calls for a provider with `id`\n`ms` would look as follows: `Authorization: Bearer oidc/ms/TOKEN`\n(replace `TOKEN` with the actual access token received from the OpenID\nConnect Provider).\n\nBack-ends MAY request user information ([including Claims](https://openid.net/specs/openid-connect-core-1_0.html#Claims))\nfrom the [OpenID Connect Userinfo endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)\nusing the access token (without the prefix described above). Therefore,\nboth openEO client and openEO back-end are relying parties (clients) to\nthe OpenID Connect Provider.", + "tags": [ + "Account Management" + ], + "security": [ + {} + ], + "responses": { + "200": { + "description": "Lists the the OpenID Connect Providers.", + "content": { + "application/json": { + "schema": { + "title": "OpenID Connect Providers", + "type": "object", + "required": [ + "providers" + ], + "properties": { + "providers": { + "type": "array", + "description": "The first provider in this list is the default provider for authentication. Clients can either pre-select or directly use the default provider for authentication if the user doesn't specify a specific value.", + "minItems": 1, + "items": { + "title": "OpenID Connect Provider", + "type": "object", + "required": [ + "id", + "issuer", + "title" + ], + "properties": { + "id": { + "type": "string", + "description": "A per-backend **unique** identifier for the OpenID Connect Provider to be as prefix for the Bearer token.", + "pattern": "[\\d\\w]{1,20}" + }, + "issuer": { + "type": "string", + "format": "uri", + "description": "The [issuer location](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig) (also referred to as 'authority' in some client libraries) is the URL of the OpenID Connect provider, which conforms to a set of rules:\n1. After appending `/.well-known/openid-configuration` to the URL, a [HTTP/1.1 GET request](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest) to the concatenated URL MUST return a [OpenID Connect Discovery Configuration Response](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). The response provides all information required to authenticate using OpenID Connect.\n2. The URL MUST NOT contain a terminating forward slash `/`.", + "example": "https://accounts.google.com" + }, + "scopes": { + "type": "array", + "description": "A list of OpenID Connect scopes that the client MUST at least include when requesting authorization. Clients MAY add additional scopes such as the `offline_access` scope to retrieve a refresh token.\nIf scopes are specified, the list MUST at least contain the `openid` scope.", + "items": { + "type": "string" + } + }, + "title": { + "type": "string", + "description": "The name that is publicly shown in clients for this OpenID Connect provider." + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "A description that explains how the authentication procedure works.\n\nIt should make clear how to register and get credentials. This should\ninclude instruction on setting up `client_id`, `client_secret` and `redirect_uri`.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich\ntext representation." + }, + "default_clients": { + "title": "Default OpenID Connect Clients", + "type": "array", + "description": "List of default OpenID Connect clients that can be used by an openEO client\nfor OpenID Connect based authentication.\n\nA default OpenID Connect client is managed by the back-end implementer.\nIt MUST be configured to be usable without a client secret,\nwhich limits its applicability to OpenID Connect grant types like\n\"Authorization Code Grant with PKCE\" and \"Device Authorization Grant with PKCE\"\n\nA default OpenID Connect client is provided without availability guarantees.\nThe back-end implementer CAN revoke, reset or update it any time.\nAs such, openEO clients SHOULD NOT store or cache default OpenID Connect client information\nfor long term usage.\nA default OpenID Connect client is intended to simplify authentication for novice users.\nFor production use cases, it is RECOMMENDED to set up a dedicated OpenID Connect client.", + "uniqueItems": true, + "items": { + "title": "Default OpenID Connect Client", "type": "object", "required": [ - "process" + "id", + "grant_types" ], "properties": { - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null_default" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" + "id": { + "type": "string", + "description": "The OpenID Connect Client ID to be used in the authentication procedure." + }, + "grant_types": { + "type": "array", + "description": "List of authorization grant types (flows) supported by the OpenID Connect client.\nA grant type descriptor consist of a OAuth 2.0 grant type,\nwith an additional `+pkce` suffix when the grant type should be used with\nthe PKCE extension as defined in [RFC 7636](https://www.rfc-editor.org/rfc/rfc7636.html).\n\nAllowed values:\n- `implicit`: Implicit Grant as specified in [RFC 6749, sec. 1.3.2](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.3.2)\n- `authorization_code` / `authorization_code+pkce`: Authorization Code Grant as specified in [RFC 6749, sec. 1.3.1](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.3.1), with or without PKCE extension.\n- `urn:ietf:params:oauth:grant-type:device_code` / `urn:ietf:params:oauth:grant-type:device_code+pkce`: Device Authorization Grant (aka Device Code Flow) as specified in [RFC 8628](https://www.rfc-editor.org/rfc/rfc8628.html), with or without PKCE extension. Note that the combination of this grant with the PKCE extension is *not standardized* yet.\n- `refresh_token`: Refresh Token as specified in [RFC 6749, sec. 1.5](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.5)", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "implicit", + "authorization_code", + "authorization_code+pkce", + "urn:ietf:params:oauth:grant-type:device_code", + "urn:ietf:params:oauth:grant-type:device_code+pkce", + "refresh_token" + ] } - }, - "additionalProperties": { - "description": "You can add additional back-end specific properties here." + }, + "redirect_urls": { + "type": "array", + "description": "List of redirect URLs that are whitelisted by the OpenID Connect client.\nRedirect URLs MUST be provided when the OpenID Connect client supports\nthe Implicit Grant or the Authorization Code Grant (with or without PKCE extension).", + "uniqueItems": true, + "items": { + "type": "string", + "format": "uri" + } + } } + } + }, + "links": { + "type": "array", + "description": "Links related to this provider, for example a\nhelp page or a page to register a new user account.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } } + } } - } + } + } + }, + "example": { + "providers": [ + { + "id": "egi", + "issuer": "https://aai.egi.eu/oidc", + "title": "EGI (default)", + "description": "Login with your academic account.", + "scopes": [ + "openid", + "profile", + "email" + ], + "default_clients": [ + { + "id": "KStcUzD5AIUA", + "grant_types": [ + "implicit", + "authorization_code+pkce", + "urn:ietf:params:oauth:grant-type:device_code+pkce", + "refresh_token" + ], + "redirect_urls": [ + "https://editor.openeo.org/" + ] + } + ] + }, + { + "id": "google", + "issuer": "https://accounts.google.com", + "title": "Google", + "description": "Login with your Google Account.", + "scopes": [ + "openid", + "profile", + "email", + "earthengine" + ] + }, + { + "id": "ms", + "issuer": "https://login.microsoftonline.com/example-tenant/v2.0", + "title": "Microsoft", + "description": "Login with your Microsoft or Skype Account.", + "scopes": [] + } + ] + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/process_graphs": { - "get": { - "summary": "List all user-defined processes", - "operationId": "list-custom-processes", - "description": "Lists all user-defined processes (process graphs) of the\nauthenticated user that are stored at the back-end.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting larger optional values from the objects in `processes`\n(e.g. the `exceptions`, `examples` and `links` properties).\nTo get the full metadata for a user-defined process clients MUST\nrequest `GET /process_graphs/{process_graph_id}`.", - "tags": [ - "User-Defined Processes", - "Process Discovery" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" + } + } + }, + "/credentials/basic": { + "get": { + "summary": "HTTP Basic authentication", + "operationId": "authenticate-basic", + "description": "Checks the credentials provided through [HTTP Basic Authentication according to RFC 7617](https://www.rfc-editor.org/rfc/rfc7617.html) and returns an access token for valid credentials.\n\nThe credentials (username and password) MUST be sent in the HTTP header `Authorization` with type `Basic` and the Base64 encoded string consisting of username and password separated by a double colon `:`. The header would look as follows for username `user` and password `pw`: `Authorization: Basic dXNlcjpwdw==`.\n\nThe access token has to be used in the Bearer token for authorization in subsequent API calls (see also the information about Bearer tokens in this document). The access token returned by this request MUST NOT be provided with `basic//` prefix, but the Bearer Token sent in subsequent API calls to protected endpoints MUST be prefixed with `basic//`. The header in subsequent API calls would look as follows: `Authorization: Bearer basic//TOKEN` (replace `TOKEN` with the actual access token).\n\nIt is RECOMMENDED to implement this authentication method for non-public services only.", + "tags": [ + "Account Management" + ], + "security": [ + { + "Basic": [] + } + ], + "responses": { + "200": { + "description": "Credentials are correct and authentication succeeded.", + "content": { + "application/json": { + "schema": { + "title": "HTTP Basic Access Token", + "type": "object", + "required": [ + "access_token" + ], + "properties": { + "access_token": { + "description": "The access token (without `basic//` prefix) to be used in the Bearer token for authorization in subsequent API calls.", + "type": "string", + "example": "b34ba2bdf9ac9ee1" + } } - ], - "responses": { - "200": { - "description": "JSON array with user-defined processes.", - "content": { - "application/json": { - "schema": { - "title": "User-Defined Processes", - "type": "object", - "required": [ - "processes", - "links" - ], - "properties": { - "processes": { - "description": "Array of user-defined processes", - "type": "array", - "items": { - "$ref": "#/components/schemas/user_defined_process_meta" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - }, - "example": { - "processes": [ - { - "id": "evi", - "summary": "Enhanced Vegetation Index", - "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", - "parameters": [ - { - "name": "red", - "description": "Value from the red band.", - "schema": { - "type": "number" - } - }, - { - "name": "blue", - "description": "Value from the blue band.", - "schema": { - "type": "number" - } - }, - { - "name": "nir", - "description": "Value from the near infrared band.", - "schema": { - "type": "number" - } - } - ], - "returns": { - "description": "Computed EVI.", - "schema": { - "type": "number" - } - } - }, - { - "id": "ndsi", - "summary": "Normalized-Difference Snow Index", - "parameters": [ - { - "name": "green", - "description": "Value from the Visible Green (0.53 - 0.61 micrometers) band.", - "schema": { - "type": "number" - } - }, - { - "name": "swir", - "description": "Value from the Short Wave Infrared (1.55 - 1.75 micrometers) band.", - "schema": { - "type": "number" - } - } - ], - "returns": { - "schema": { - "type": "number" - } - } - }, - { - "id": "my_custom_process" - } - ], - "links": [] - } - } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/validation": { + "post": { + "summary": "Validate a user-defined process (graph)", + "operationId": "validate-custom-process", + "description": "Validates a user-defined process without executing it. A user-defined process is\nconsidered valid unless the `errors` array in the response contains at\nleast one error.\n\nChecks whether the process graph is schematically correct and the\nprocesses are supported by the back-end. It MUST also check the\narguments against the schema, but checking whether the arguments are\nadequate in the context of data is OPTIONAL. For example, a non-existing\nband name may get rejected only by a few back-ends.\nThe validation MUST NOT throw an error for unresolvable process parameters.\n\nBack-ends MUST validate the process graph. Validating the corresponding\nmetadata is OPTIONAL.\n\nErrors that usually occur during processing MAY NOT get reported, e.g.\nif a referenced file is accessible at the time of execution.\n\nBack-ends can either report all errors at once or stop the validation\nonce they found the first error. \n\nPlease note that a validation always returns with HTTP status code 200.\nError codes in the 4xx and 5xx ranges MUST be returned only when the\ngeneral validation request is invalid (e.g. server is busy or properties\nin the request body are missing), but never if an error was found during\nvalidation of the user-defined process (e.g. an unsupported process).", + "tags": [ + "Data Processing", + "User-Defined Processes" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Returns the validation result as a list of errors. An empty list indicates a successful validation.", + "content": { + "application/json": { + "schema": { + "title": "Validation Result", + "type": "object", + "required": [ + "errors" + ], + "properties": { + "errors": { + "description": "A list of validation errors.", + "type": "array", + "items": { + "$ref": "#/components/schemas/error" } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + } } + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/process_graphs/{process_graph_id}": { - "parameters": [ - { - "name": "process_graph_id", - "in": "path", - "description": "Per-user unique identifier for a user-defined process.", - "required": true, - "schema": { - "$ref": "#/components/schemas/process_id" - } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "examples": { + "evi_user_defined_process": { + "$ref": "#/components/examples/evi_user_defined_process" + } } - ], - "get": { - "summary": "Full metadata for a user-defined process", - "operationId": "describe-custom-process", - "description": "Lists all information about a user-defined process, including its process graph.", - "tags": [ - "User-Defined Processes", - "Process Discovery" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "The user-defined process with process graph.", - "content": { - "application/json": { - "schema": { - "title": "User-Defined Process", - "description": "A user-defined process with processing instructions as process graph.", - "type": "object", - "required": [ - "process_graph" - ], - "allOf": [ - { - "$ref": "#/components/schemas/user_defined_process_meta" - } - ] - }, - "examples": { - "evi_user_defined_process": { - "$ref": "#/components/examples/evi_user_defined_process" - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } + } + }, + "description": "Specifies the user-defined process to be validated." + } + } + }, + "/result": { + "post": { + "summary": "Process and download data synchronously", + "operationId": "compute-result", + "description": "Executes a user-defined process directly (synchronously) and the result will be downloaded in the format specified in the process graph. This endpoint can be used to generate small previews or test user-defined processes before starting a batch job.\nTimeouts on either client- or server-side are to be expected for complex computations. Back-ends MAY send the openEO error `ProcessGraphComplexity` immediately if the computation is expected to time out. Otherwise requests MAY time-out after a certain amount of time by sending openEO error `RequestTimeout`.\nA header named `OpenEO-Costs` MAY be sent with all responses, which MUST include the costs for processing and downloading the data. Additionally, a link to a log file MAY be sent in the header.", + "tags": [ + "Data Processing" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Result data in the requested output format", + "headers": { + "Content-Type": { + "description": "The appropriate media (MIME) type for the requested output\nformat MUST be sent, if the response contains a single file.\n\nTo send multiple files at once it is RECOMMENDED to use the\n[`tar` file format](https://www.gnu.org/software/tar/manual/html_node/Standard.html)\n(media type: `application/x-tar`).\n\nTo mimic the results of batch jobs, it is RECOMMENDED that \n1. clients extract the tar file directly after receiving it so that users\n can directly work on the contained files *and*\n2. back-ends add STAC Items and/or Collections to the tar file\n so that users can make sense of the files.", + "schema": { + "type": "string" + } + }, + "OpenEO-Costs": { + "description": "MAY include the costs for processing and downloading the data.", + "schema": { + "$ref": "#/components/schemas/money" + } + }, + "Link": { + "description": "The header MAY indicate a link to a log file generated by the request. If provided, the link MUST be serialized according to [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288.html#section-3) and MUST use the relation type `monitor`. The link MUST follow the specifications for the links `GET /jobs/{job_id}/logs` and `GET /services/{service_id}/logs`, except that is MUST NOT accept any parameters (limit/offset). Therefore, the link MUST be accessible with HTTP GET, MUST be secured using a Bearer token and MUST follow the corresponding request body schema.", + "schema": { + "type": "string", + "pattern": "^<[^>]+>;\\s?rel=\"monitor\"", + "example": "; rel=\"monitor\"" + } } + } }, - "put": { - "summary": "Store a user-defined process", - "operationId": "store-custom-process", - "description": "Stores a provided user-defined process with process graph that can be\nreused in other processes.\n\nIf a process with the specified `process_graph_id` exists, the process\nis fully replaced. The id can't be changed for existing user-defined\nprocesses. The id MUST be unique across its namespace.\n\nPartially updating user-defined processes is not supported.\n\nTo simplify exchanging user-defined processes, the property `id` can be part of\nthe request body. If the values don't match, the value for `id` gets\nreplaced with the value from the `process_graph_id` parameter in the\npath.", - "tags": [ - "User-Defined Processes" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "The user-defined process has been stored successfully." + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "description": "Specifies the job details, e.g. the user-defined process and billing details.", + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Synchronous Result Request", + "type": "object", + "required": [ + "process" + ], + "properties": { + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "budget": { + "$ref": "#/components/schemas/budget" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan_null_default" }, - "5XX": { - "$ref": "#/components/responses/server_error" + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" } - }, - "requestBody": { - "required": true, - "description": "Specifies the process graph with its meta data.", - "content": { - "application/json": { + }, + "additionalProperties": { + "description": "You can add additional back-end specific properties here." + } + } + } + } + } + } + }, + "/process_graphs": { + "get": { + "summary": "List all user-defined processes", + "operationId": "list-custom-processes", + "description": "Lists all user-defined processes (process graphs) of the\nauthenticated user that are stored at the back-end.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting larger optional values from the objects in `processes`\n(e.g. the `exceptions`, `examples` and `links` properties).\nTo get the full metadata for a user-defined process clients MUST\nrequest `GET /process_graphs/{process_graph_id}`.", + "tags": [ + "User-Defined Processes", + "Process Discovery" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "JSON array with user-defined processes.", + "content": { + "application/json": { + "schema": { + "title": "User-Defined Processes", + "type": "object", + "required": [ + "processes", + "links" + ], + "properties": { + "processes": { + "description": "Array of user-defined processes", + "type": "array", + "items": { + "$ref": "#/components/schemas/user_defined_process_meta" + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + }, + "example": { + "processes": [ + { + "id": "evi", + "summary": "Enhanced Vegetation Index", + "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", + "parameters": [ + { + "name": "red", + "description": "Value from the red band.", "schema": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "examples": { - "evi_user_defined_process": { - "$ref": "#/components/examples/evi_user_defined_process" - } + "type": "number" + } + }, + { + "name": "blue", + "description": "Value from the blue band.", + "schema": { + "type": "number" + } + }, + { + "name": "nir", + "description": "Value from the near infrared band.", + "schema": { + "type": "number" } + } + ], + "returns": { + "description": "Computed EVI.", + "schema": { + "type": "number" + } } - } + }, + { + "id": "ndsi", + "summary": "Normalized-Difference Snow Index", + "parameters": [ + { + "name": "green", + "description": "Value from the Visible Green (0.53 - 0.61 micrometers) band.", + "schema": { + "type": "number" + } + }, + { + "name": "swir", + "description": "Value from the Short Wave Infrared (1.55 - 1.75 micrometers) band.", + "schema": { + "type": "number" + } + } + ], + "returns": { + "schema": { + "type": "number" + } + } + }, + { + "id": "my_custom_process" + } + ], + "links": [] + } } + } }, - "delete": { - "summary": "Delete a user-defined process", - "operationId": "delete-custom-process", - "description": "Deletes the data related to this user-defined process, including its process graph.\n\nDoes NOT delete jobs or services that reference this user-defined process.", - "tags": [ - "User-Defined Processes" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "The user-defined process has been successfully deleted" - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/process_graphs/{process_graph_id}": { + "parameters": [ + { + "name": "process_graph_id", + "in": "path", + "description": "Per-user unique identifier for a user-defined process.", + "required": true, + "schema": { + "$ref": "#/components/schemas/process_id" + } + } + ], + "get": { + "summary": "Full metadata for a user-defined process", + "operationId": "describe-custom-process", + "description": "Lists all information about a user-defined process, including its process graph.", + "tags": [ + "User-Defined Processes", + "Process Discovery" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "The user-defined process with process graph.", + "content": { + "application/json": { + "schema": { + "title": "User-Defined Process", + "description": "A user-defined process with processing instructions as process graph.", + "type": "object", + "required": [ + "process_graph" + ], + "allOf": [ + { + "$ref": "#/components/schemas/user_defined_process_meta" + } + ] + }, + "examples": { + "evi_user_defined_process": { + "$ref": "#/components/examples/evi_user_defined_process" } + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } + } }, - "/service_types": { - "get": { - "summary": "Supported secondary web service protocols", - "operationId": "list-service-types", - "description": "Lists supported secondary web service protocols such as\n[OGC WMS](http://www.opengeospatial.org/standards/wms),\n[OGC WCS](http://www.opengeospatial.org/standards/wcs),\n[OGC API - Features](https://www.ogc.org/standards/ogcapi-features)\nor [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).\nThe response is an object of all available secondary web service protocols\nwith their supported configuration settings and expected process parameters.\n\n* The configuration settings for the service SHOULD be defined upon\n creation of a service and the service will be set up accordingly.\n* The process parameters SHOULD be referenced (with a `from_parameter`\n reference) in the user-defined process that is used to compute web service\n results.\n The appropriate arguments MUST be provided to the user-defined process,\n usually at runtime from the context of the web service,\n For example, a map service such as a WMS would\n need to inject the spatial extent into the user-defined process so that the\n back-end can compute the corresponding tile correctly.\n\nTo improve interoperability between back-ends common names for the\nservices SHOULD be used, e.g. the abbreviations used in the official\n[OGC Schema Repository](http://schemas.opengis.net/) for the respective\nservices.\n\nService names MUST be accepted in a *case insensitive* manner throughout the API.", - "tags": [ - "Capabilities", - "Secondary Services" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "An object with a map containing all service names as keys and an object that defines supported configuration settings and process parameters.", - "content": { - "application/json": { - "schema": { - "title": "Service Types", - "type": "object", - "description": "Map of supported secondary web services.", - "additionalProperties": { - "x-additionalPropertiesName": "Service Name", - "title": "Service Type", - "type": "object", - "required": [ - "configuration", - "process_parameters" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/object_title" - }, - "description": { - "$ref": "#/components/schemas/description" - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "configuration": { - "title": "Service Configuration", - "description": "Map of supported configuration settings made available to the creator of the service.", - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/resource_parameter" - } - }, - "process_parameters": { - "title": "Process Parameters", - "description": "List of parameters made available to user-defined processes.", - "type": "array", - "items": { - "$ref": "#/components/schemas/process_parameter" - } - }, - "links": { - "description": "Links related to this service type, e.g. more\ninformation about the configuration settings and process parameters.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - } - } - } - } - }, - "example": { - "WMS": { - "title": "OGC Web Map Service", - "configuration": { - "version": { - "type": "string", - "description": "The WMS version offered to consumers of the service.", - "default": "1.3.0", - "enum": [ - "1.1.1", - "1.3.0" - ] - } - }, - "process_parameters": [ - { - "name": "layer", - "description": "The layer name.", - "schema": { - "type": "string" - }, - "default": "roads" - }, - { - "name": "spatial_extent", - "description": "A bounding box in WGS84.", - "schema": { - "type": "object", - "required": [ - "west", - "south", - "east", - "north" - ], - "properties": { - "west": { - "description": "West (lower left corner, coordinate axis 1).", - "type": "number" - }, - "south": { - "description": "South (lower left corner, coordinate axis 2).", - "type": "number" - }, - "east": { - "description": "East (upper right corner, coordinate axis 1).", - "type": "number" - }, - "north": { - "description": "North (upper right corner, coordinate axis 2).", - "type": "number" - } - } - } - } - ], - "links": [ - { - "href": "https://www.opengeospatial.org/standards/wms", - "rel": "about", - "title": "OGC Web Map Service Standard" - } - ] - }, - "OGCAPI-FEATURES": { - "title": "OGC API - Features", - "description": "Exposes a OGC API - Features in version 1.0 of the specification (successor of OGC WFS 3.0).", - "configuration": { - "title": { - "type": "string", - "description": "The title for the OGC API - Features landing page" - }, - "description": { - "type": "string", - "description": "The description for the OGC API - Features landing page" - }, - "conformsTo": { - "type": "array", - "description": "The OGC API - Features conformance classes to enable for this service.\n\n`http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core` is always enabled.", - "items": { - "type": "string", - "enum": [ - "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30", - "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/html", - "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson", - "http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs" - ] - } - } - }, - "process_parameters": [], - "links": [ - { - "href": "https://www.opengeospatial.org/standards/wfs", - "rel": "about", - "title": "OGC Web Feature Service Standard" - } - ] - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } + "put": { + "summary": "Store a user-defined process", + "operationId": "store-custom-process", + "description": "Stores a provided user-defined process with process graph that can be\nreused in other processes.\n\nIf a process with the specified `process_graph_id` exists, the process\nis fully replaced. The id can't be changed for existing user-defined\nprocesses. The id MUST be unique across its namespace.\n\nPartially updating user-defined processes is not supported.\n\nTo simplify exchanging user-defined processes, the property `id` can be part of\nthe request body. If the values don't match, the value for `id` gets\nreplaced with the value from the `process_graph_id` parameter in the\npath.", + "tags": [ + "User-Defined Processes" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "The user-defined process has been stored successfully." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "description": "Specifies the process graph with its meta data.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + "examples": { + "evi_user_defined_process": { + "$ref": "#/components/examples/evi_user_defined_process" + } } + } } + } }, - "/services": { - "get": { - "summary": "List all web services", - "operationId": "list-services", - "description": "Lists all secondary web services submitted by a user.\n\nIt is **strongly RECOMMENDED** to keep the response size small by omitting\nall optional non-scalar values (i.e. arrays and objects) from objects in `services`\n(i.e. the `process`, `configuration` and `attributes` properties).\nTo get the full metadata for a secondary web service clients MUST\nrequest `GET /services/{service_id}`.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Array of secondary web service descriptions", - "content": { - "application/json": { - "schema": { - "title": "Secondary Web Services", - "type": "object", - "required": [ - "services", - "links" - ], - "properties": { - "services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/service" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - } + "delete": { + "summary": "Delete a user-defined process", + "operationId": "delete-custom-process", + "description": "Deletes the data related to this user-defined process, including its process graph.\n\nDoes NOT delete jobs or services that reference this user-defined process.", + "tags": [ + "User-Defined Processes" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "The user-defined process has been successfully deleted" + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/service_types": { + "get": { + "summary": "Supported secondary web service protocols", + "operationId": "list-service-types", + "description": "Lists supported secondary web service protocols such as\n[OGC WMS](http://www.opengeospatial.org/standards/wms),\n[OGC WCS](http://www.opengeospatial.org/standards/wcs),\n[OGC API - Features](https://www.ogc.org/standards/ogcapi-features)\nor [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).\nThe response is an object of all available secondary web service protocols\nwith their supported configuration settings and expected process parameters.\n\n* The configuration settings for the service SHOULD be defined upon\n creation of a service and the service will be set up accordingly.\n* The process parameters SHOULD be referenced (with a `from_parameter`\n reference) in the user-defined process that is used to compute web service\n results.\n The appropriate arguments MUST be provided to the user-defined process,\n usually at runtime from the context of the web service,\n For example, a map service such as a WMS would\n need to inject the spatial extent into the user-defined process so that the\n back-end can compute the corresponding tile correctly.\n\nTo improve interoperability between back-ends common names for the\nservices SHOULD be used, e.g. the abbreviations used in the official\n[OGC Schema Repository](http://schemas.opengis.net/) for the respective\nservices.\n\nService names MUST be accepted in a *case insensitive* manner throughout the API.", + "tags": [ + "Capabilities", + "Secondary Services" + ], + "security": [ + {}, + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "An object with a map containing all service names as keys and an object that defines supported configuration settings and process parameters.", + "content": { + "application/json": { + "schema": { + "title": "Service Types", + "type": "object", + "description": "Map of supported secondary web services.", + "additionalProperties": { + "x-additionalPropertiesName": "Service Name", + "title": "Service Type", + "type": "object", + "required": [ + "configuration", + "process_parameters" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/object_title" + }, + "description": { + "$ref": "#/components/schemas/description" + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "configuration": { + "title": "Service Configuration", + "description": "Map of supported configuration settings made available to the creator of the service.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/resource_parameter" + } + }, + "process_parameters": { + "title": "Process Parameters", + "description": "List of parameters made available to user-defined processes.", + "type": "array", + "items": { + "$ref": "#/components/schemas/process_parameter" + } + }, + "links": { + "description": "Links related to this service type, e.g. more\ninformation about the configuration settings and process parameters.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + } + } + } + } + }, + "example": { + "WMS": { + "title": "OGC Web Map Service", + "configuration": { + "version": { + "type": "string", + "description": "The WMS version offered to consumers of the service.", + "default": "1.3.0", + "enum": [ + "1.1.1", + "1.3.0" + ] + } + }, + "process_parameters": [ + { + "name": "layer", + "description": "The layer name.", + "schema": { + "type": "string" + }, + "default": "roads" + }, + { + "name": "spatial_extent", + "description": "A bounding box in WGS84.", + "schema": { + "type": "object", + "required": [ + "west", + "south", + "east", + "north" + ], + "properties": { + "west": { + "description": "West (lower left corner, coordinate axis 1).", + "type": "number" + }, + "south": { + "description": "South (lower left corner, coordinate axis 2).", + "type": "number" + }, + "east": { + "description": "East (upper right corner, coordinate axis 1).", + "type": "number" + }, + "north": { + "description": "North (upper right corner, coordinate axis 2).", + "type": "number" + } } + } } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + ], + "links": [ + { + "href": "https://www.opengeospatial.org/standards/wms", + "rel": "about", + "title": "OGC Web Map Service Standard" + } + ] + }, + "OGCAPI-FEATURES": { + "title": "OGC API - Features", + "description": "Exposes a OGC API - Features in version 1.0 of the specification (successor of OGC WFS 3.0).", + "configuration": { + "title": { + "type": "string", + "description": "The title for the OGC API - Features landing page" + }, + "description": { + "type": "string", + "description": "The description for the OGC API - Features landing page" + }, + "conformsTo": { + "type": "array", + "description": "The OGC API - Features conformance classes to enable for this service.\n\n`http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core` is always enabled.", + "items": { + "type": "string", + "enum": [ + "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30", + "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/html", + "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson", + "http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs" + ] + } + } + }, + "process_parameters": [], + "links": [ + { + "href": "https://www.opengeospatial.org/standards/wfs", + "rel": "about", + "title": "OGC Web Feature Service Standard" + } + ] } + } } + } }, - "post": { - "summary": "Publish a new service", - "operationId": "create-service", - "description": "Creates a new secondary web service such as a\n[OGC WMS](http://www.opengeospatial.org/standards/wms),\n[OGC WCS](http://www.opengeospatial.org/standards/wcs),\n[OGC API - Features](https://www.ogc.org/standards/ogcapi-features)\nor [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).\n\nThe secondary web service SHOULD process the underlying\ndata on demand, based on process parameters provided to the\nuser-defined process (through `from_parameter` references) at run-time,\nfor example for the spatial/temporal extent, resolution, etc.\nThe available process parameters are specified per\nservice type at `GET /service_types`.\n\n**Note:** Costs incurred by shared secondary web services are usually\npaid by the owner, but this depends on the service type and whether it\nsupports charging fees or not.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "201": { - "description": "The service has been created successfully.", - "headers": { - "Location": { - "required": true, - "schema": { - "description": "Absolute URL to the newly created service.\n\nThe URL points to the metadata endpoint\n`GET /services/{service_id}` with the `{service_id}` being the\nunique identifier (ID) of the created service.\nMUST NOT point to the actual instance (e.g. WMTS base URL) of\nthe service. The URL to the instance is made available by the\nmetadata endpoint in the property `url`.", - "format": "uri", - "type": "string", - "example": "https://openeo.example/api/v1/services/123" - } - }, - "OpenEO-Identifier": { - "required": true, - "schema": { - "$ref": "#/components/schemas/service_id" - } - } + "4XX": { + "$ref": "#/components/responses/client_error" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/services": { + "get": { + "summary": "List all web services", + "operationId": "list-services", + "description": "Lists all secondary web services submitted by a user.\n\nIt is **strongly RECOMMENDED** to keep the response size small by omitting\nall optional non-scalar values (i.e. arrays and objects) from objects in `services`\n(i.e. the `process`, `configuration` and `attributes` properties).\nTo get the full metadata for a secondary web service clients MUST\nrequest `GET /services/{service_id}`.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Array of secondary web service descriptions", + "content": { + "application/json": { + "schema": { + "title": "Secondary Web Services", + "type": "object", + "required": [ + "services", + "links" + ], + "properties": { + "services": { + "type": "array", + "items": { + "$ref": "#/components/schemas/service" } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Store Secondary Web Service Request", - "type": "object", - "required": [ - "type", - "process" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "type": { - "$ref": "#/components/schemas/service_type" - }, - "enabled": { - "allOf": [ - { - "$ref": "#/components/schemas/service_enabled" - }, - { - "default": true - } - ] - }, - "configuration": { - "$ref": "#/components/schemas/service_configuration" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null_default" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - } - }, - "additionalProperties": { - "description": "You can add additional back-end specific properties here." - } - } - } - }, - "description": "The base data for the secondary web service to create" + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } + } }, - "/services/{service_id}": { - "parameters": [ - { - "$ref": "#/components/parameters/service_id" + "post": { + "summary": "Publish a new service", + "operationId": "create-service", + "description": "Creates a new secondary web service such as a\n[OGC WMS](http://www.opengeospatial.org/standards/wms),\n[OGC WCS](http://www.opengeospatial.org/standards/wcs),\n[OGC API - Features](https://www.ogc.org/standards/ogcapi-features)\nor [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).\n\nThe secondary web service SHOULD process the underlying\ndata on demand, based on process parameters provided to the\nuser-defined process (through `from_parameter` references) at run-time,\nfor example for the spatial/temporal extent, resolution, etc.\nThe available process parameters are specified per\nservice type at `GET /service_types`.\n\n**Note:** Costs incurred by shared secondary web services are usually\npaid by the owner, but this depends on the service type and whether it\nsupports charging fees or not.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "201": { + "description": "The service has been created successfully.", + "headers": { + "Location": { + "required": true, + "schema": { + "description": "Absolute URL to the newly created service.\n\nThe URL points to the metadata endpoint\n`GET /services/{service_id}` with the `{service_id}` being the\nunique identifier (ID) of the created service.\nMUST NOT point to the actual instance (e.g. WMTS base URL) of\nthe service. The URL to the instance is made available by the\nmetadata endpoint in the property `url`.", + "format": "uri", + "type": "string", + "example": "https://openeo.example/api/v1/services/123" + } + }, + "OpenEO-Identifier": { + "required": true, + "schema": { + "$ref": "#/components/schemas/service_id" + } } - ], - "patch": { - "summary": "Modify a service", - "operationId": "update-service", - "description": "Modifies an existing secondary web service at the back-end,\nbut maintain the identifier. Changes can be grouped in a single request.\n\nUser have to create a new service to change the service type.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "Changes to the service were applied successfully." + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Store Secondary Web Service Request", + "type": "object", + "required": [ + "type", + "process" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/eo_title" }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "description": { + "$ref": "#/components/schemas/eo_description" }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Update Secondary Web Service Request", - "type": "object", - "properties": { - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "enabled": { - "$ref": "#/components/schemas/service_enabled" - }, - "configuration": { - "$ref": "#/components/schemas/service_configuration" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null" - }, - "budget": { - "$ref": "#/components/schemas/budget_update" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_update" - } - } - } - } + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" }, - "description": "The data to change for the specified secondary web service." - } - }, - "get": { - "summary": "Full metadata for a service", - "operationId": "describe-service", - "description": "Lists all information about a secondary web service.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Details of the created service", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "process", - "configuration", - "attributes" - ], - "allOf": [ - { - "$ref": "#/components/schemas/service" - } - ] - } - } + "type": { + "$ref": "#/components/schemas/service_type" + }, + "enabled": { + "allOf": [ + { + "$ref": "#/components/schemas/service_enabled" + }, + { + "default": true } + ] }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "configuration": { + "$ref": "#/components/schemas/service_configuration" }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "delete": { - "summary": "Delete a service", - "operationId": "delete-service", - "description": "Deletes all data related to this secondary web service. Computations are stopped, computed results are deleted and access to this is not possible any more. This service won't generate additional costs.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "The service has been successfully deleted." + "plan": { + "$ref": "#/components/schemas/billing_plan_null_default" }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "budget": { + "$ref": "#/components/schemas/budget" }, - "5XX": { - "$ref": "#/components/responses/server_error" + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" } + }, + "additionalProperties": { + "description": "You can add additional back-end specific properties here." + } } + } + }, + "description": "The base data for the secondary web service to create" + } + } + }, + "/services/{service_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/service_id" + } + ], + "patch": { + "summary": "Modify a service", + "operationId": "update-service", + "description": "Modifies an existing secondary web service at the back-end,\nbut maintain the identifier. Changes can be grouped in a single request.\n\nUser have to create a new service to change the service type.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] } - }, - "/services/{service_id}/logs": { - "get": { - "summary": "Logs for a secondary service", - "operationId": "debug-service", - "description": "Lists log entries for the secondary service, usually for debugging purposes.\nBack-ends can log any information that may be relevant for a user. Users can log information during data processing using respective processes such as `inspect`.\nIf requested consecutively while the secondary service is enabled, it is RECOMMENDED that clients use the offset parameter to get only the entries they have not received yet.\nWhile pagination itself is OPTIONAL, the `offset` parameter is REQUIRED to be implemented by back-ends.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/service_id" - }, - { - "$ref": "#/components/parameters/log_offset" + ], + "responses": { + "204": { + "description": "Changes to the service were applied successfully." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Update Secondary Web Service Request", + "type": "object", + "properties": { + "title": { + "$ref": "#/components/schemas/eo_title" }, - { - "$ref": "#/components/parameters/log_level" + "description": { + "$ref": "#/components/schemas/eo_description" }, - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/logs" + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "enabled": { + "$ref": "#/components/schemas/service_enabled" }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/jobs": { - "get": { - "summary": "List all batch jobs", - "operationId": "list-jobs", - "description": "Lists all batch jobs submitted by a user.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting all optional non-scalar values (i.e. arrays and objects) from\nobjects in `jobs` (i.e. the `process` property).\nTo get the full metadata for a job clients MUST request `GET /jobs/{job_id}`.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Array of job descriptions", - "content": { - "application/json": { - "schema": { - "title": "Batch Jobs", - "type": "object", - "required": [ - "jobs", - "links" - ], - "properties": { - "jobs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/batch_job" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - } - } - } + "configuration": { + "$ref": "#/components/schemas/service_configuration" }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "plan": { + "$ref": "#/components/schemas/billing_plan_null" + }, + "budget": { + "$ref": "#/components/schemas/budget_update" }, - "5XX": { - "$ref": "#/components/responses/server_error" + "log_level": { + "$ref": "#/components/schemas/min_log_level_update" } + } } + } }, - "post": { - "summary": "Create a new batch job", - "operationId": "create-job", - "description": "Creates a new batch processing task (job) from one or more (chained)\nprocesses at the back-end.\n\nProcessing the data doesn't start yet. The job status gets initialized\nas `created` by default.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "201": { - "description": "The batch job has been created successfully.", - "headers": { - "Location": { - "required": true, - "schema": { - "description": "Absolute URL to the newly created batch job.\n\nThe URL points to the metadata endpoint\n`GET /jobs/{job_id}` with the `{job_id}` being the\nunique identifier (ID) of the created batch job.", - "format": "uri", - "type": "string", - "example": "https://openeo.example/api/v1/jobs/123" - } - }, - "OpenEO-Identifier": { - "required": true, - "schema": { - "$ref": "#/components/schemas/job_id" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Store Batch Job Request", - "type": "object", - "required": [ - "process" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null_default" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - } - }, - "additionalProperties": { - "description": "You can add additional back-end specific properties here." - } - } - } - }, - "description": "Specifies the job details, e.g. the user-defined process and billing details." + "description": "The data to change for the specified secondary web service." + } + }, + "get": { + "summary": "Full metadata for a service", + "operationId": "describe-service", + "description": "Lists all information about a secondary web service.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Details of the created service", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "process", + "configuration", + "attributes" + ], + "allOf": [ + { + "$ref": "#/components/schemas/service" + } + ] + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } + } }, - "/jobs/{job_id}": { - "parameters": [ - { - "$ref": "#/components/parameters/job_id" - } - ], - "patch": { - "summary": "Modify a batch job", - "operationId": "update-job", - "description": "Modifies an existing job at the back-end, but maintains the identifier.\nChanges can be grouped in a single request.\n\nThe job status does not change.\n\nJobs can only be modified when the job is not queued and not running.\nOtherwise, requests to this endpoint MUST be rejected with openEO error\n`JobLocked`.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "Changes to the job applied successfully." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Update Batch Job Request", - "type": "object", - "properties": { - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null" - }, - "budget": { - "$ref": "#/components/schemas/budget_update" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_update" - } - } - } - } - }, - "description": "Specifies the job details to update." - } + "delete": { + "summary": "Delete a service", + "operationId": "delete-service", + "description": "Deletes all data related to this secondary web service. Computations are stopped, computed results are deleted and access to this is not possible any more. This service won't generate additional costs.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "The service has been successfully deleted." }, - "get": { - "summary": "Full metadata for a batch job", - "operationId": "describe-job", - "description": "Lists all information about a submitted batch job.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Full job information.", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "process" - ], - "allOf": [ - { - "$ref": "#/components/schemas/batch_job" - } - ] - } - } + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/services/{service_id}/logs": { + "get": { + "summary": "Logs for a secondary service", + "operationId": "debug-service", + "description": "Lists log entries for the secondary service, usually for debugging purposes.\nBack-ends can log any information that may be relevant for a user. Users can log information during data processing using respective processes such as `inspect`.\nIf requested consecutively while the secondary service is enabled, it is RECOMMENDED that clients use the offset parameter to get only the entries they have not received yet.\nWhile pagination itself is OPTIONAL, the `offset` parameter is REQUIRED to be implemented by back-ends.", + "tags": [ + "Secondary Services" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/service_id" + }, + { + "$ref": "#/components/parameters/log_offset" + }, + { + "$ref": "#/components/parameters/log_level" + }, + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/logs" + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/jobs": { + "get": { + "summary": "List all batch jobs", + "operationId": "list-jobs", + "description": "Lists all batch jobs submitted by a user.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting all optional non-scalar values (i.e. arrays and objects) from\nobjects in `jobs` (i.e. the `process` property).\nTo get the full metadata for a job clients MUST request `GET /jobs/{job_id}`.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Array of job descriptions", + "content": { + "application/json": { + "schema": { + "title": "Batch Jobs", + "type": "object", + "required": [ + "jobs", + "links" + ], + "properties": { + "jobs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/batch_job" } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } } + } } + } }, - "delete": { - "summary": "Delete a batch job", - "operationId": "delete-job", - "description": "Deletes all data related to this job. Computations are stopped and computed results are deleted. This job won't generate additional costs for processing.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "The job has been successfully deleted." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } + } }, - "/jobs/{job_id}/estimate": { - "get": { - "summary": "Get an estimate for a batch job", - "operationId": "estimate-job", - "description": "Calculates an estimate for a batch job. Back-ends can decide to either calculate the duration, the costs, the size or a combination of them.\nBack-end providers MAY specify an expiry time for the estimate. Starting to process data afterwards MAY be charged at a higher cost. Costs do often not include download costs. Whether download costs are included or not can be indicated explicitly with the `downloads_included` flag.\nThe estimate SHOULD be the upper limit of the costs, but back-end are free to use the field according to their terms of service.\nFor some batch jobs it is not (easily) possible to estimate the costs reliably, e.g. if a UDF or ML model is part of the process. In this case, the server SHOULD return a `EstimateComplexity` error with HTTP status code 500.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/job_id" - } - ], - "responses": { - "200": { - "description": "The estimated costs with regard to money, processing time and storage capacity. At least one of `costs`, `duration` or `size` MUST be provided.", - "content": { - "application/json": { - "schema": { - "title": "Batch Job Estimate", - "type": "object", - "anyOf": [ - { - "required": [ - "costs" - ] - }, - { - "required": [ - "duration" - ] - }, - { - "required": [ - "size" - ] - } - ], - "properties": { - "costs": { - "$ref": "#/components/schemas/money" - }, - "duration": { - "type": "string", - "description": "Estimated duration for the operation. Duration MUST be specified as a ISO 8601 duration.", - "example": "P1Y2M10DT2H30M" - }, - "size": { - "type": "integer", - "description": "Estimated required storage capacity, i.e. the size of the generated files. Size MUST be specified in bytes.", - "example": 157286400 - }, - "downloads_included": { - "type": "integer", - "nullable": true, - "description": "Specifies how many full downloads of the processed data are included in the estimate. Set to `null` for unlimited downloads, which is also the default value.", - "example": 5, - "default": null - }, - "expires": { - "type": "string", - "format": "date-time", - "description": "Time until which the estimate is valid, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2020-11-01T00:00:00Z" - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } + "post": { + "summary": "Create a new batch job", + "operationId": "create-job", + "description": "Creates a new batch processing task (job) from one or more (chained)\nprocesses at the back-end.\n\nProcessing the data doesn't start yet. The job status gets initialized\nas `created` by default.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "201": { + "description": "The batch job has been created successfully.", + "headers": { + "Location": { + "required": true, + "schema": { + "description": "Absolute URL to the newly created batch job.\n\nThe URL points to the metadata endpoint\n`GET /jobs/{job_id}` with the `{job_id}` being the\nunique identifier (ID) of the created batch job.", + "format": "uri", + "type": "string", + "example": "https://openeo.example/api/v1/jobs/123" + } + }, + "OpenEO-Identifier": { + "required": true, + "schema": { + "$ref": "#/components/schemas/job_id" + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/jobs/{job_id}/logs": { - "get": { - "summary": "Logs for a batch job", - "operationId": "debug-job", - "description": "Lists log entries for the batch job, usually for debugging purposes.\n\nBack-ends can log any information that may be relevant for a user\nat any stage (status) of the batch job.\nUsers can log information during data processing using respective\nprocesses such as `inspect`.\n\nIf requested consecutively, it is RECOMMENDED that clients use the offset\nparameter to get only the entries they have not received yet.\n\nWhile pagination itself is OPTIONAL, the `offset` parameter is REQUIRED\nto be implemented by back-ends.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/job_id" + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Store Batch Job Request", + "type": "object", + "required": [ + "process" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/eo_title" }, - { - "$ref": "#/components/parameters/log_offset" + "description": { + "$ref": "#/components/schemas/eo_description" }, - { - "$ref": "#/components/parameters/log_level" + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" }, - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/logs" + "plan": { + "$ref": "#/components/schemas/billing_plan_null_default" }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "budget": { + "$ref": "#/components/schemas/budget" }, - "5XX": { - "$ref": "#/components/responses/server_error" + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" } + }, + "additionalProperties": { + "description": "You can add additional back-end specific properties here." + } } + } + }, + "description": "Specifies the job details, e.g. the user-defined process and billing details." + } + } + }, + "/jobs/{job_id}": { + "parameters": [ + { + "$ref": "#/components/parameters/job_id" + } + ], + "patch": { + "summary": "Modify a batch job", + "operationId": "update-job", + "description": "Modifies an existing job at the back-end, but maintains the identifier.\nChanges can be grouped in a single request.\n\nThe job status does not change.\n\nJobs can only be modified when the job is not queued and not running.\nOtherwise, requests to this endpoint MUST be rejected with openEO error\n`JobLocked`.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] } - }, - "/jobs/{job_id}/results": { - "parameters": [ - { - "$ref": "#/components/parameters/job_id" - } - ], - "get": { - "summary": "List batch job results", - "operationId": "list-results", - "description": "Lists signed URLs pointing to the processed files, usually after the batch job\nhas finished. Back-ends may also point to intermediate results after the\njob has stopped due to an error or if the `partial` parameter has been set.\n\nThe response includes additional metadata. It is a valid\n[STAC Item](https://github.com/radiantearth/stac-spec/tree/v1.0.0/item-spec)\n(if it has spatial and temporal references included) or a valid\n[STAC Collection](https://github.com/radiantearth/stac-spec/tree/v1.0.0/collection-spec)\n(supported since openEO API version 1.1.0).\nThe assets to download are in both cases available in the property `assets`\nand have the same structure. All additional metadata is not strictly required\nto download the files, but are helpful for users to understand the data.\n\nSTAC Collections can either (1) add all assets as collection-level assets or\n(2) link to STAC Catalogs and STAC Items with signed URLs, which will provide a full\nSTAC catalog structure a client has to go through. Option 2 is overall the better \narchitectural choice and allows a fine-grained description of the processed data,\nbut it is not compliant with previous versions of the openEO API.\n**To maintain backward compatibility, it is REQUIRED to still copy\nall assets in the STAC catalog structure into the collection-level assets.**\nThis requirement is planned to be removed in openEO API version 2.0.0.\nA client can enforce that the server returns a GeoJSON through content negotiation\nwith the media type `application/geo+json`, but the results may not contain very\nmeaningful metadata aside from the assets.\n\nClients are RECOMMENDED to store this response and all potential sub-catalogs\nand items with the assets so that the downloaded data is then a self-contained\nSTAC catalog user could publish easily with all the data and metadata.\n\nURL signing is a way to protect files from unauthorized access with a\nkey in the URL instead of HTTP header based authorization. The URL\nsigning key is similar to a password and its inclusion in the URL allows\nto download files using simple GET requests supported by a wide range of\nprograms, e.g. web browsers or download managers. Back-ends are\nresponsible to generate the URL signing keys and to manage their\nappropriate expiration. The back-end MAY indicate an expiration time by\nsetting the `expires` property in the reponse. Requesting this endpoint\nSHOULD always return non-expired URLs. Signed URLs that were generated\nfor a previous request and already expired SHOULD NOT be reused,\nbut regenerated with new expiration time.\nSigned URLs that expired MAY return the openEO error `ResultLinkExpired`.\n\nIt is **strongly recommended** to add a link with relation type `canonical`\nto the STAC Item or STAC Collection (see the `links` property for details).\n\nIf processing has not finished yet and the `partial` parameter is not set to `true`\nrequests to this endpoint MUST be rejected with openEO error `JobNotFinished`.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "name": "partial", - "description": "If set to `true`, the results endpoint returns incomplete results while still running.\nEnabling this parameter requires to indicate the status of the batch job in the STAC metadata by setting the `openeo:status`.", - "in": "query", - "allowEmptyValue": true, - "schema": { - "type": "boolean", - "default": false - } - } - ], - "responses": { - "200": { - "description": "Valid download links have been returned. The download links doesn't necessarily need to be located under the API base url.", - "headers": { - "OpenEO-Costs": { - "description": "Specifies the costs for fully downloading the data **once**, i.e. this header MAY change in subsequent calls. It MUST be set to `0` if the requester is the owner of the job and still has free downloads included in his processing charges estimated by `GET /jobs/{job_id}/estimate`. If a requester other than the owner is requesting the data of a shared job this header indicates the costs for the requester.", - "schema": { - "$ref": "#/components/schemas/money" - } - } - }, - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/batch_job_result" - }, - { - "title": "Batch Job Results Response as STAC Collection", - "type": "object", - "required": [ - "assets" - ], - "properties": { - "openeo:status": { - "$ref": "#/components/schemas/result_status" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/collection" - } - ], - "example": { - "stac_version": "1.0.0", - "id": "a3cca2b2aa1e3b5b", - "title": "NDVI based on Sentinel 2", - "description": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2", - "license": "Apache-2.0", - "providers": [ - { - "name": "Example Cloud Corp.", - "description": "No further processing applied.", - "roles": [ - "producer", - "licensor", - "host" - ], - "url": "https://cloud.example" - } - ], - "extent": { - "temporal": { - "interval": [ - [ - "2019-08-24T14:15:22Z", - "2019-08-24T14:15:22Z" - ] - ] - }, - "spatial": { - "bbox": [ - [ - -180, - -90, - 180, - 90 - ] - ] - } - }, - "assets": { - "preview.png": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/preview.png", - "type": "image/png", - "title": "Thumbnail", - "roles": [ - "thumbnail" - ] - }, - "process.json": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/process.json", - "type": "application/json", - "title": "Original Process", - "roles": [ - "process", - "reproduction" - ] - }, - "1.tif": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/1.tif", - "type": "image/tiff; application=geotiff", - "roles": [ - "data" - ] - }, - "2.tif": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/2.tif", - "type": "image/tiff; application=geotiff", - "roles": [ - "data" - ] - }, - "inspire.xml": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/inspire.xml", - "type": "application/xml", - "title": "INSPIRE metadata", - "description": "INSPIRE compliant XML metadata", - "roles": [ - "metadata" - ] - } - }, - "links": [ - { - "rel": "canonical", - "type": "application/json", - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/collection.json" - }, - { - "rel": "item", - "type": "application/geo+json", - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item_1.json" - }, - { - "rel": "item", - "type": "application/geo+json", - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item_2.json" - } - ] - } - } - ] - } - }, - "application/geo+json": { - "schema": { - "$ref": "#/components/schemas/batch_job_result" - } - } - } + ], + "responses": { + "204": { + "description": "Changes to the job applied successfully." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "title": "Update Batch Job Request", + "type": "object", + "properties": { + "title": { + "$ref": "#/components/schemas/eo_title" }, - "424": { - "description": "The request can't be fulfilled as the batch job failed. This request will deliver the last error message that was produced by the batch job.\n\nThis HTTP code MUST be sent only when the job `status` is `error`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/log_entry" - } - } - } + "description": { + "$ref": "#/components/schemas/eo_description" }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "post": { - "summary": "Start processing a batch job", - "operationId": "start-job", - "description": "Adds a batch job to the processing queue to compute the results.\n\nThe result will be stored in the format specified in the process.\nTo specify the format use a process such as `save_result`.\n\nThe job status is set to `queued`, if processing doesn't start\ninstantly. The same applies if the job status is `canceled`, `finished`,\nor `error`, which restarts the job and discards previous results if the\nback-end doesn't reject the request with an error.\nClients SHOULD warn users and ask for confirmation if results may get\ndiscarded.\n\n* Once the processing starts the status is set to `running`.\n* Once the data is available to download the status is set to\n`finished`.\n* Whenever an error occurs during processing, the status MUST be set to\n`error`.\n\nThis endpoint has no effect if the job status is already `queued` or\n`running`. In particular, it doesn't restart a running job. To restart\na queued or running job, processing MUST have been canceled before.\n\nBack-ends SHOULD reject queueing jobs with openEO error `PaymentRequired`,\nif the back-end is able to detect that the budget is too low to fully\nprocess the request. Alternatively, back-ends MAY provide partial results\nonce reaching the budget. If none of the alternatives is feasible, the\nresults are discarded. Thus, client SHOULD warn users that reaching the\nbudget may lead to partial or no results at all.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "202": { - "description": "The creation of the resource has been queued successfully." + "plan": { + "$ref": "#/components/schemas/billing_plan_null" }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" + "budget": { + "$ref": "#/components/schemas/budget_update" }, - "5XX": { - "$ref": "#/components/responses/server_error" + "log_level": { + "$ref": "#/components/schemas/min_log_level_update" } + } } + } }, - "delete": { - "summary": "Cancel processing a batch job", - "operationId": "stop-job", - "description": "Cancels all related computations for this job at the back-end. It will\nstop generating additional costs for processing.\n\nA subset of processed results may be available for downloading depending\non the state of the job at the time it was canceled.\n\nResults MUST NOT be deleted until the job processing is started again or\nthe job is completely deleted through a request to\n`DELETE /jobs/{job_id}`.\n\nThis endpoint only has an effect if the job status is `queued` or\n`running`.\n\nThe job status is set to `canceled` if the status was `running`\nbeforehand and partial or preliminary results are available to be\ndownloaded. Otherwise the status is set to `created`. ", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "Processing the job has been successfully canceled." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } + "description": "Specifies the job details to update." + } }, - "/files": { - "get": { - "summary": "List all files in the workspace", - "operationId": "list-files", - "description": "Lists all user-uploaded files that are stored at the back-end.", - "tags": [ - "File Storage" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Flattened file tree with path relative to the user's root directory and some basic properties such as the file size and the timestamp of the last modification. All properties except the name are optional. Folders MUST NOT be listed separately so each element in the list MUST be a downloadable file.", - "content": { - "application/json": { - "schema": { - "title": "Workspace Files", - "type": "object", - "required": [ - "files", - "links" - ], - "properties": { - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/file" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - }, - "example": { - "files": [ - { - "path": "test.txt", - "size": 182, - "modified": "2015-10-20T17:22:10Z" - }, - { - "path": "test.tif", - "size": 183142, - "modified": "2017-01-01T09:36:18Z" - }, - { - "path": "Sentinel2/S2A_MSIL1C_20170819T082011_N0205_R121_T34KGD_20170819T084427.zip", - "size": 4183353142, - "modified": "2018-01-03T10:55:29Z" - } - ], - "links": [] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } + "get": { + "summary": "Full metadata for a batch job", + "operationId": "describe-job", + "description": "Lists all information about a submitted batch job.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Full job information.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "process" + ], + "allOf": [ + { + "$ref": "#/components/schemas/batch_job" + } + ] + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } + } }, - "/files/{path}": { - "parameters": [ - { - "name": "path", - "in": "path", - "description": "Path of the file, relative to the user's root directory. MAY include folders, but MUST not include relative references such as `.` and `..`.\n\nFolder and file names in the path MUST be url-encoded. The path separator `/` and the file extension separator `.` MUST NOT be url-encoded.\n\nThe URL-encoding may be shown incorrectly in rendered versions due to [OpenAPI 3 not supporting path parameters which contain slashes](https://github.com/OAI/OpenAPI-Specification/issues/892). This may also lead to OpenAPI validators not validating paths containing folders correctly.", - "required": true, - "schema": { - "type": "string" - }, - "examples": { - "normal": { - "description": "A path without special chars. It describes a file `europe.geojson` in a folder called `borders`.", - "value": "borders/europe.geojson" - }, - "specialchars": { - "description": "A path with special chars. It describes a file `m\u00fcnster.shp` in folders called `europe` and `\u00f6sterreich`.", - "value": "europe/%C3%B6sterreich/m%C3%BCnster.shp" - } - } - } - ], - "get": { - "summary": "Download a file from the workspace", - "operationId": "download-file", - "description": "Offers a file from the user workspace for download. The file is identified by its path relative to the user's root directory.\nIf a folder is specified as path a `FileOperationUnsupported` error MUST be sent as response.", - "tags": [ - "File Storage" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "A file from the workspace.", - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } + "delete": { + "summary": "Delete a batch job", + "operationId": "delete-job", + "description": "Deletes all data related to this job. Computations are stopped and computed results are deleted. This job won't generate additional costs for processing.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "The job has been successfully deleted." }, - "put": { - "summary": "Upload a file to the workspace", - "operationId": "upload-file", - "description": "Uploads a new file to the given path or updates an existing file if a file at the path exists.\n\nFolders are created once required by a file upload. Empty folders can't be created.", - "tags": [ - "File Storage" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "The file has been uploaded successfully.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/file" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - } + "4XX": { + "$ref": "#/components/responses/client_error_auth" }, - "delete": { - "summary": "Delete a file from the workspace", - "operationId": "delete-file", - "description": "Deletes an existing user-uploaded file specified by its path. Resulting empty folders MUST be deleted automatically.\n\nBack-ends MAY support deleting folders including its files and sub-folders. If not supported by the back-end a `FileOperationUnsupported` error MUST be sent as response.", - "tags": [ - "File Storage" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "The file has been successfully deleted at the back-end." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } + "5XX": { + "$ref": "#/components/responses/server_error" } - }, - "/me": { - "get": { - "summary": "Information about the authenticated user", - "operationId": "describe-account", - "description": "Lists information about the authenticated user, e.g. the user id.\nThe endpoint MAY return the disk quota available to the user. The endpoint MAY also return links related to user management and the user profile, e.g. where payments are handled or the user profile could be edited.\nFor back-ends that involve accounting, this service MAY also return the currently available money or credits in the currency the back-end is working with.\nThis endpoint MAY be extended to fulfil the specification of the [OpenID Connect UserInfo Endpoint](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo).", - "tags": [ - "Account Management" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Information about the logged in user.", - "content": { - "application/json": { - "schema": { - "title": "User Data", - "description": "Holds user information. If no budget or storage limit applies to the user account the corresponding properties MUST be set to null.", - "type": "object", - "required": [ - "user_id" - ], - "properties": { - "user_id": { - "type": "string", - "description": "A unique user identifier specific to the back-end, which could either be chosen by a user or is automatically generated by the back-end during the registration process at the back-end.\nIt is meant to be used as an identifier in URIs (e.g. for sharing purposes), which is primarily used in machine-to-machine communication. Preferrably use the human-readable property `name` to display the user's name in user interfaces instead of the user identifier.", - "pattern": "^[\\w\\-\\.~]+$", - "example": "john_doe" - }, - "name": { - "type": "string", - "description": "The user name, a human-friendly displayable name. Could be the user's real name or a nickname." - }, - "default_plan": { - "type": "string", - "description": "Name of the single plan the user is currently subscribed to if any.", - "example": "free" - }, - "storage": { - "title": "User Storage", - "description": "Information about the storage space available to the user.", - "type": "object", - "nullable": true, - "required": [ - "free", - "quota" - ], - "properties": { - "free": { - "type": "integer", - "description": "Free storage space in bytes, which is still available to the user. Effectively, this is the disk quota minus the used space by the user, e.g. user-uploaded files and job results.", - "example": 536870912 - }, - "quota": { - "type": "integer", - "description": "Maximum storage space (disk quota) in bytes available to the user.", - "example": 1073741824 - } - } - }, - "budget": { - "type": "number", - "nullable": true, - "description": "The remaining budget a user has available.\nThe value MUST be specified in the currency of the back-end.\nThe value SHOULD be set to `null` if no explicit limit applies." - }, - "links": { - "description": "Links related to the user profile, e.g. where payments\nare handled or the user profile could be edited.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `payment`: A page where users can recharge their user account with money or credits.\n\n2. `edit-form`: Points to a page where the user can edit his user profile.\n\n3. `alternate`: Any other representation of these (and potentially additional)\nuser information, e.g. the (public) user profile page.\nIt is RECOMMENDED to add descriptive titles for a better user experience.\n\n4. `related`: Any other user-specific links to be shown in clients,\ne.g. to user-specific settings, invoices, etc. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "href": "https://openeo.example/john_doe/payment/", - "rel": "payment" - }, - { - "href": "https://openeo.example/john_doe/edit/", - "rel": "edit-form" - }, - { - "href": "https://openeo.example/john_doe/", - "rel": "alternate", - "type": "text/html", - "title": "User profile" - }, - { - "href": "https://openeo.example/john_doe.vcf", - "rel": "alternate", - "type": "text/vcard", - "title": "vCard of John Doe" - }, - { - "href": "https://openeo.example/john_doe/invoices", - "rel": "related", - "type": "text/html", - "title": "Invoices" - } - ] - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" + } + } + }, + "/jobs/{job_id}/estimate": { + "get": { + "summary": "Get an estimate for a batch job", + "operationId": "estimate-job", + "description": "Calculates an estimate for a batch job. Back-ends can decide to either calculate the duration, the costs, the size or a combination of them.\nBack-end providers MAY specify an expiry time for the estimate. Starting to process data afterwards MAY be charged at a higher cost. Costs do often not include download costs. Whether download costs are included or not can be indicated explicitly with the `downloads_included` flag.\nThe estimate SHOULD be the upper limit of the costs, but back-end are free to use the field according to their terms of service.\nFor some batch jobs it is not (easily) possible to estimate the costs reliably, e.g. if a UDF or ML model is part of the process. In this case, the server SHOULD return a `EstimateComplexity` error with HTTP status code 500.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/job_id" + } + ], + "responses": { + "200": { + "description": "The estimated costs with regard to money, processing time and storage capacity. At least one of `costs`, `duration` or `size` MUST be provided.", + "content": { + "application/json": { + "schema": { + "title": "Batch Job Estimate", + "type": "object", + "anyOf": [ + { + "required": [ + "costs" + ] + }, + { + "required": [ + "duration" + ] + }, + { + "required": [ + "size" + ] + } + ], + "properties": { + "costs": { + "$ref": "#/components/schemas/money" + }, + "duration": { + "type": "string", + "description": "Estimated duration for the operation. Duration MUST be specified as a ISO 8601 duration.", + "example": "P1Y2M10DT2H30M" + }, + "size": { + "type": "integer", + "description": "Estimated required storage capacity, i.e. the size of the generated files. Size MUST be specified in bytes.", + "example": 157286400 + }, + "downloads_included": { + "type": "integer", + "nullable": true, + "description": "Specifies how many full downloads of the processed data are included in the estimate. Set to `null` for unlimited downloads, which is also the default value.", + "example": 5, + "default": null + }, + "expires": { + "type": "string", + "format": "date-time", + "description": "Time until which the estimate is valid, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2020-11-01T00:00:00Z" + } } + } } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" } + } } - }, - "components": { - "schemas": { - "conformsTo": { - "description": "Lists all conformance classes specified in various standards that the\nimplementation conforms to. Conformance classes are commonly used in\nall OGC APIs and the STAC API specification.\n\nThe general openEO conformance class is `https://api.openeo.org/1.2.0`.\nSee the individual openEO API extensions for their conformance classes.\n\nThis property is REQUIRED for STAC API versions 1.0.0-beta.1 and later.", - "type": "array", - "items": { - "type": "string", - "format": "uri" - }, - "example": [ - "https://api.openeo.org/1.2.0", - "https://api.openeo.org/extensions/commercial-data/0.1.0", - "https://api.openeo.org/extensions/federation/0.1.0", - "https://api.stacspec.org/v1.0.0/collections" - ] + }, + "/jobs/{job_id}/logs": { + "get": { + "summary": "Logs for a batch job", + "operationId": "debug-job", + "description": "Lists log entries for the batch job, usually for debugging purposes.\n\nBack-ends can log any information that may be relevant for a user\nat any stage (status) of the batch job.\nUsers can log information during data processing using respective\nprocesses such as `inspect`.\n\nIf requested consecutively, it is RECOMMENDED that clients use the offset\nparameter to get only the entries they have not received yet.\n\nWhile pagination itself is OPTIONAL, the `offset` parameter is REQUIRED\nto be implemented by back-ends.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/job_id" }, - "udf_runtime": { - "type": "object", - "required": [ - "type", - "default" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/object_title" - }, - "description": { - "$ref": "#/components/schemas/description" - }, - "type": { - "type": "string", - "description": "The type of the UDF runtime.\n\nPredefined types are:\n* `language` for Programming Languages and\n* `docker` for Docker Containers.\n\nThe types can potentially be extended by back-ends." - }, - "default": { - "type": "string" - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "links": { - "type": "array", - "description": "Links related to this runtime, e.g. external documentation.\n\nIt is highly RECOMMENDED to provide at least links with\nthe following `rel` (relation) types:\n\n1. `about`: A resource that further explains the runtime,\ne.g. a user guide or the documentation. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - } - }, - "discriminator": { - "propertyName": "type", - "mapping": { - "language": "#/components/schemas/udf_programming_language", - "docker": "#/components/schemas/udf_docker" - } - } + { + "$ref": "#/components/parameters/log_offset" }, - "udf_programming_language": { - "allOf": [ - { - "$ref": "#/components/schemas/udf_runtime" - }, - { - "title": "Programming language", - "required": [ - "versions" - ], - "properties": { - "default": { - "type": "string", - "description": "The default version. MUST be one of the keys in the `versions` object." - }, - "versions": { - "title": "Programming language versions", - "description": "Versions available for the programming language.", - "type": "object", - "additionalProperties": { - "x-additionalPropertiesName": "Programming Language Version", - "title": "Programming language version", - "type": "object", - "required": [ - "libraries" - ], - "properties": { - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "libraries": { - "description": "Map of installed libraries, modules, packages or extensions for the programming language. The names of them are used as the property keys.", - "additionalProperties": { - "x-additionalPropertiesName": "Library Name", - "title": "Programming language library", - "type": "object", - "required": [ - "version" - ], - "properties": { - "version": { - "type": "string", - "description": "Version number of the library." - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "links": { - "type": "array", - "description": "Additional links related to this library,\ne.g. external documentation for this library.\n\nIt is highly RECOMMENDED to provide links with\nthe following `rel` (relation) types:\n\n1. `about`: A resource that further explains the library,\ne.g. a user guide or the documentation. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\n2. `latest-version`: If a library has been marked as deprecated,\na link SHOULD point to either a new library replacing the deprecated\nlibrary or a latest version of the library available at the back-end.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - } - } - } - } - } - } - } - } - } - ] + { + "$ref": "#/components/parameters/log_level" }, - "udf_docker": { - "allOf": [ - { - "$ref": "#/components/schemas/udf_runtime" - }, - { - "title": "Docker container", + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/logs" + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/jobs/{job_id}/results": { + "parameters": [ + { + "$ref": "#/components/parameters/job_id" + } + ], + "get": { + "summary": "List batch job results", + "operationId": "list-results", + "description": "Lists signed URLs pointing to the processed files, usually after the batch job\nhas finished. Back-ends may also point to intermediate results after the\njob has stopped due to an error or if the `partial` parameter has been set.\n\nThe response includes additional metadata. It is a valid\n[STAC Item](https://github.com/radiantearth/stac-spec/tree/v1.0.0/item-spec)\n(if it has spatial and temporal references included) or a valid\n[STAC Collection](https://github.com/radiantearth/stac-spec/tree/v1.0.0/collection-spec)\n(supported since openEO API version 1.1.0).\nThe assets to download are in both cases available in the property `assets`\nand have the same structure. All additional metadata is not strictly required\nto download the files, but are helpful for users to understand the data.\n\nSTAC Collections can either (1) add all assets as collection-level assets or\n(2) link to STAC Catalogs and STAC Items with signed URLs, which will provide a full\nSTAC catalog structure a client has to go through. Option 2 is overall the better \narchitectural choice and allows a fine-grained description of the processed data,\nbut it is not compliant with previous versions of the openEO API.\n**To maintain backward compatibility, it is REQUIRED to still copy\nall assets in the STAC catalog structure into the collection-level assets.**\nThis requirement is planned to be removed in openEO API version 2.0.0.\nA client can enforce that the server returns a GeoJSON through content negotiation\nwith the media type `application/geo+json`, but the results may not contain very\nmeaningful metadata aside from the assets.\n\nClients are RECOMMENDED to store this response and all potential sub-catalogs\nand items with the assets so that the downloaded data is then a self-contained\nSTAC catalog user could publish easily with all the data and metadata.\n\nURL signing is a way to protect files from unauthorized access with a\nkey in the URL instead of HTTP header based authorization. The URL\nsigning key is similar to a password and its inclusion in the URL allows\nto download files using simple GET requests supported by a wide range of\nprograms, e.g. web browsers or download managers. Back-ends are\nresponsible to generate the URL signing keys and to manage their\nappropriate expiration. The back-end MAY indicate an expiration time by\nsetting the `expires` property in the reponse. Requesting this endpoint\nSHOULD always return non-expired URLs. Signed URLs that were generated\nfor a previous request and already expired SHOULD NOT be reused,\nbut regenerated with new expiration time.\nSigned URLs that expired MAY return the openEO error `ResultLinkExpired`.\n\nIt is **strongly recommended** to add a link with relation type `canonical`\nto the STAC Item or STAC Collection (see the `links` property for details).\n\nIf processing has not finished yet and the `partial` parameter is not set to `true`\nrequests to this endpoint MUST be rejected with openEO error `JobNotFinished`.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "name": "partial", + "description": "If set to `true`, the results endpoint returns incomplete results while still running.\nEnabling this parameter requires to indicate the status of the batch job in the STAC metadata by setting the `openeo:status`.", + "in": "query", + "allowEmptyValue": true, + "schema": { + "type": "boolean", + "default": false + } + } + ], + "responses": { + "200": { + "description": "Valid download links have been returned. The download links doesn't necessarily need to be located under the API base url.", + "headers": { + "OpenEO-Costs": { + "description": "Specifies the costs for fully downloading the data **once**, i.e. this header MAY change in subsequent calls. It MUST be set to `0` if the requester is the owner of the job and still has free downloads included in his processing charges estimated by `GET /jobs/{job_id}/estimate`. If a requester other than the owner is requesting the data of a shared job this header indicates the costs for the requester.", + "schema": { + "$ref": "#/components/schemas/money" + } + } + }, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/batch_job_result" + }, + { + "title": "Batch Job Results Response as STAC Collection", + "type": "object", "required": [ - "docker", - "tags" + "assets" ], "properties": { - "docker": { - "type": "string", - "description": "Identifier of a Docker image on Docker Hub or a private repository, which can run openEO UDFs. This is what is used in the `docker pull` command excluding the tag, e.g. `php`, `mcr.microsoft.com/dotnet/runtime` or `myregistry.local:5000/testing/test-image`." - }, - "default": { - "type": "string", - "description": "The default tag. MUST be one of the values in the `tags` array." - }, - "tags": { - "type": "array", - "description": "The docker tags that are supported.", - "minItems": 1, - "items": { - "type": "string" - } - } - } - } - ] - }, - "result_status": { - "type": "string", - "enum": [ - "running", - "canceled", - "finished", - "error" - ], - "description": "The status of a batch job.\n\nThis field is REQUIRED if the `partial` parameter is given.\nThis field is strongly RECOMMENDED if the job has stopped due to an error.", - "default": "finished" - }, - "batch_job_result": { - "title": "Batch Job Results Response as STAC Item", - "description": "The STAC specification should be the main guidance for implementing this.\nSpecifying the `bbox` is strongly RECOMMENDED for STAC compliance, but can be omitted if the result is unlocated and the `geometry` is set to `null`.", - "type": "object", - "required": [ - "stac_version", - "id", - "type", - "geometry", - "properties", - "assets", - "links" - ], - "properties": { - "stac_version": { - "$ref": "#/components/schemas/stac_version" - }, - "stac_extensions": { - "$ref": "#/components/schemas/stac_extensions" - }, - "id": { - "$ref": "#/components/schemas/job_id" - }, - "type": { - "type": "string", - "description": "The GeoJSON type that applies to this metadata document, which MUST always be a \"Feature\" according to the STAC specification.\nThis type does **not** describe the spatial data type of the assets.", - "enum": [ - "Feature" - ] - }, - "bbox": { - "$ref": "#/components/schemas/bbox" - }, - "geometry": { - "description": "Defines the full footprint of the asset represented by this item as\nGeoJSON Geometry.\n\nResults without a known location can set this value to `null`.", - "nullable": true, + "openeo:status": { + "$ref": "#/components/schemas/result_status" + } + }, "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - } + { + "$ref": "#/components/schemas/collection" + } ], "example": { - "type": "Polygon", - "coordinates": [ + "stac_version": "1.0.0", + "id": "a3cca2b2aa1e3b5b", + "title": "NDVI based on Sentinel 2", + "description": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2", + "license": "Apache-2.0", + "providers": [ + { + "name": "Example Cloud Corp.", + "description": "No further processing applied.", + "roles": [ + "producer", + "licensor", + "host" + ], + "url": "https://cloud.example" + } + ], + "extent": { + "temporal": { + "interval": [ [ - [ - -180, - -90 - ], - [ - 180, - -90 - ], - [ - 180, - 90 - ], - [ - -180, - 90 - ], - [ - -180, - -90 - ] + "2019-08-24T14:15:22Z", + "2019-08-24T14:15:22Z" ] - ] - } - }, - "properties": { - "type": "object", - "title": "Item Properties", - "description": "MAY contain additional properties other than the required property `datetime`, e.g. custom properties or properties from the STAC specification or STAC extensions.", - "required": [ - "datetime" - ], - "additionalProperties": true, - "properties": { - "datetime": { - "title": "Date and Time", - "description": "The searchable date/time of the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.\n\nIf this field is set to `null` (usually for larger time ranges), it is STRONGLY RECOMMENDED to specify both `start_datetime` and `end_datetime` for STAC compliance.", - "type": "string", - "format": "date-time", - "nullable": true - }, - "start_datetime": { - "type": "string", - "format": "date-time", - "description": "For time series: The first or start date and time for the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." - }, - "end_datetime": { - "type": "string", - "format": "date-time", - "description": "For time series: The last or end date and time for the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." - }, - "title": { - "$ref": "#/components/schemas/eo_title" + ] }, - "description": { - "$ref": "#/components/schemas/eo_description" + "spatial": { + "bbox": [ + [ + -180, + -90, + 180, + 90 + ] + ] + } + }, + "assets": { + "preview.png": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/preview.png", + "type": "image/png", + "title": "Thumbnail", + "roles": [ + "thumbnail" + ] }, - "license": { - "$ref": "#/components/schemas/stac_license" + "process.json": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/process.json", + "type": "application/json", + "title": "Original Process", + "roles": [ + "process", + "reproduction" + ] }, - "providers": { - "$ref": "#/components/schemas/stac_providers" + "1.tif": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/1.tif", + "type": "image/tiff; application=geotiff", + "roles": [ + "data" + ] }, - "created": { - "$ref": "#/components/schemas/created" + "2.tif": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/2.tif", + "type": "image/tiff; application=geotiff", + "roles": [ + "data" + ] }, - "updated": { - "$ref": "#/components/schemas/updated" + "inspire.xml": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/inspire.xml", + "type": "application/xml", + "title": "INSPIRE metadata", + "description": "INSPIRE compliant XML metadata", + "roles": [ + "metadata" + ] + } + }, + "links": [ + { + "rel": "canonical", + "type": "application/json", + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/collection.json" }, - "expires": { - "type": "string", - "format": "date-time", - "description": "Time until which the assets are accessible, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2020-11-01T00:00:00Z" + { + "rel": "item", + "type": "application/geo+json", + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item_1.json" }, - "openeo:status": { - "$ref": "#/components/schemas/result_status" - } - } - }, - "assets": { - "$ref": "#/components/schemas/stac_assets" - }, - "links": { - "type": "array", - "description": "Links related to this batch job result, e.g. a link to an \ninvoice, additional log files or external documentation.\n\nThe links MUST NOT contain links to the processed and\ndownloadable data. Instead specify these in the `assets` property.\nClients MUST NOT download the data referenced in the links by\ndefault.\n\nIt is **strongly recommended** to add a link with relation type\n`canonical`, which points to this STAC document using a signed URL.\nThis way the STAC metadata can be used by non-openEO clients\nwithout additional authentication steps.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ { - "rel": "canonical", - "type": "application/geo+json", - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item.json" + "rel": "item", + "type": "application/geo+json", + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item_2.json" } - ] - } + ] + } + } + ] + } + }, + "application/geo+json": { + "schema": { + "$ref": "#/components/schemas/batch_job_result" + } } + } }, - "file_format": { - "x-additionalPropertiesName": "File Format Name", - "title": "File Format", - "type": "object", - "description": "Describes a specific file format.", - "required": [ - "gis_data_types", - "parameters" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/object_title" - }, - "description": { - "$ref": "#/components/schemas/description" - }, - "gis_data_types": { - "type": "array", - "description": "Specifies the supported GIS spatial data types for this format.\nIt is RECOMMENDED to specify at least one of the data types, which will likely become a requirement in a future API version.", - "items": { - "type": "string", - "enum": [ - "raster", - "vector", - "table", - "pointcloud", - "other" - ] - } - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "parameters": { - "title": "File Format Parameters", - "description": "Specifies the supported parameters for this file format.", - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/resource_parameter" - } - }, - "links": { - "type": "array", - "description": "Links related to this file format, e.g. external documentation.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - } + "424": { + "description": "The request can't be fulfilled as the batch job failed. This request will deliver the last error message that was produced by the batch job.\n\nThis HTTP code MUST be sent only when the job `status` is `error`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/log_entry" + } } + } }, - "production": { - "type": "boolean", - "description": "Specifies whether the implementation is ready to be used in production use (`true`) or not (`false`).\nClients SHOULD only connect to non-production implementations if the user explicitly confirmed to use a non-production implementation.\nThis flag is part of `GET /.well-known/openeo` and `GET /`. It MUST be used consistently in both endpoints.", - "default": false + "4XX": { + "$ref": "#/components/responses/client_error_auth" }, - "links_pagination": { - "description": "Links related to this list of resources, for example links for pagination\nor alternative formats such as a human-readable HTML version.\nThe links array MUST NOT be paginated.\n\nIf pagination is implemented, the following `rel` (relation) types apply:\n\n1. `next` (REQUIRED): A link to the next page, except on the last page.\n\n2. `prev` (OPTIONAL): A link to the previous page, except on the first page.\n\n3. `first` (OPTIONAL): A link to the first page, except on the first page.\n\n4. `last` (OPTIONAL): A link to the last page, except on the last page.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - } + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "post": { + "summary": "Start processing a batch job", + "operationId": "start-job", + "description": "Adds a batch job to the processing queue to compute the results.\n\nThe result will be stored in the format specified in the process.\nTo specify the format use a process such as `save_result`.\n\nThe job status is set to `queued`, if processing doesn't start\ninstantly. The same applies if the job status is `canceled`, `finished`,\nor `error`, which restarts the job and discards previous results if the\nback-end doesn't reject the request with an error.\nClients SHOULD warn users and ask for confirmation if results may get\ndiscarded.\n\n* Once the processing starts the status is set to `running`.\n* Once the data is available to download the status is set to\n`finished`.\n* Whenever an error occurs during processing, the status MUST be set to\n`error`.\n\nThis endpoint has no effect if the job status is already `queued` or\n`running`. In particular, it doesn't restart a running job. To restart\na queued or running job, processing MUST have been canceled before.\n\nBack-ends SHOULD reject queueing jobs with openEO error `PaymentRequired`,\nif the back-end is able to detect that the budget is too low to fully\nprocess the request. Alternatively, back-ends MAY provide partial results\nonce reaching the budget. If none of the alternatives is feasible, the\nresults are discarded. Thus, client SHOULD warn users that reaching the\nbudget may lead to partial or no results at all.", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "202": { + "description": "The creation of the resource has been queued successfully." }, - "link": { - "title": "Link", - "description": "A link to another resource on the web. Bases on [RFC 5899](https://www.rfc-editor.org/rfc/rfc5988.html).", - "type": "object", - "required": [ - "href", - "rel" - ], - "properties": { - "rel": { - "type": "string", - "description": "Relationship between the current document and the linked document. SHOULD be a [registered link relation type](https://www.iana.org/assignments/link-relations/link-relations.xml) whenever feasible.", - "example": "related" - }, - "href": { - "type": "string", - "description": "The value MUST be a valid URL.", - "format": "uri", - "example": "https://openeo.example" - }, - "type": { - "type": "string", - "description": "The value MUST be a string that hints at the format used to represent data at the provided URI, preferably a media (MIME) type.", - "example": "text/html" - }, - "title": { - "type": "string", - "description": "Used as a human-readable label for a link.", - "example": "openEO" - } - } + "4XX": { + "$ref": "#/components/responses/client_error_auth" }, - "asset": { - "title": "STAC Asset", - "type": "object", - "required": [ - "href" - ], - "properties": { - "href": { - "title": "Asset location", - "description": "URL to the downloadable asset.\nThe URLs SHOULD be available without authentication so that external clients can download them easily. If the data is confidential, signed URLs SHOULD be used to protect against unauthorized access from third parties.", - "type": "string" - }, - "title": { - "description": "The displayed title for clients and users.", - "type": "string" - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "Multi-line description to explain the asset.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich\ntext representation." - }, - "type": { - "title": "Media Type", - "description": "Media type of the asset.", - "type": "string", - "example": "image/tiff; application=geotiff" - }, - "roles": { + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "delete": { + "summary": "Cancel processing a batch job", + "operationId": "stop-job", + "description": "Cancels all related computations for this job at the back-end. It will\nstop generating additional costs for processing.\n\nA subset of processed results may be available for downloading depending\non the state of the job at the time it was canceled.\n\nResults MUST NOT be deleted until the job processing is started again or\nthe job is completely deleted through a request to\n`DELETE /jobs/{job_id}`.\n\nThis endpoint only has an effect if the job status is `queued` or\n`running`.\n\nThe job status is set to `canceled` if the status was `running`\nbeforehand and partial or preliminary results are available to be\ndownloaded. Otherwise the status is set to `created`. ", + "tags": [ + "Data Processing", + "Batch Jobs" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "Processing the job has been successfully canceled." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/files": { + "get": { + "summary": "List all files in the workspace", + "operationId": "list-files", + "description": "Lists all user-uploaded files that are stored at the back-end.", + "tags": [ + "File Storage" + ], + "security": [ + { + "Bearer": [] + } + ], + "parameters": [ + { + "$ref": "#/components/parameters/pagination_limit" + } + ], + "responses": { + "200": { + "description": "Flattened file tree with path relative to the user's root directory and some basic properties such as the file size and the timestamp of the last modification. All properties except the name are optional. Folders MUST NOT be listed separately so each element in the list MUST be a downloadable file.", + "content": { + "application/json": { + "schema": { + "title": "Workspace Files", + "type": "object", + "required": [ + "files", + "links" + ], + "properties": { + "files": { "type": "array", "items": { - "type": "string" - }, - "description": "Purposes of the asset. Can be any value, but commonly used values are:\n\n* `thumbnail`: A visualization of the data, usually a lower-resolution true color image in JPEG or PNG format.\n* `reproducibility`: Information how the data was produced and/or can be reproduced, e.g. the process graph used to compute the data in JSON format.\n* `data`: The computed data in the format specified by the user in the process graph (applicable in `GET /jobs/{job_id}/results` only).\n* `metadata`: Additional metadata available for the computed data.", - "example": [ - "data" - ] - } + "$ref": "#/components/schemas/file" + } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } + } + }, + "example": { + "files": [ + { + "path": "test.txt", + "size": 182, + "modified": "2015-10-20T17:22:10Z" + }, + { + "path": "test.tif", + "size": 183142, + "modified": "2017-01-01T09:36:18Z" + }, + { + "path": "Sentinel2/S2A_MSIL1C_20170819T082011_N0205_R121_T34KGD_20170819T084427.zip", + "size": 4183353142, + "modified": "2018-01-03T10:55:29Z" + } + ], + "links": [] + } } + } }, - "money": { - "description": "An amount of money or credits. The value MUST be specified in the currency the back-end is working with. The currency can be retrieved by calling `GET /`. If no currency is set, this field MUST be `null`.", - "type": "number", - "minimum": 0, - "example": 12.98, - "nullable": true, - "default": null + "4XX": { + "$ref": "#/components/responses/client_error_auth" }, - "budget": { - "type": "number", - "minimum": 0, - "nullable": true, - "description": "Maximum amount of costs the request is allowed to produce.\nThe value MUST be specified in the currency of the back-end.\nNo limits apply, if the value is `null` or the back-end has no currency\nset in `GET /`.", - "example": 100, - "default": null - }, - "budget_update": { - "type": "number", - "minimum": 0, - "nullable": true, - "description": "Maximum amount of costs the request is allowed to produce.\nThe value MUST be specified in the currency of the back-end.\nNo limits apply, if the value is `null`.", - "example": 100 - }, - "billing_plan": { - "type": "string", - "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be handled in a *case insensitive* manner.\n\nThe plans can be retrieved from `GET /`, but the value returned here may\nnot be in the list of plans any longer.", - "example": "free" + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/files/{path}": { + "parameters": [ + { + "name": "path", + "in": "path", + "description": "Path of the file, relative to the user's root directory. MAY include folders, but MUST not include relative references such as `.` and `..`.\n\nFolder and file names in the path MUST be url-encoded. The path separator `/` and the file extension separator `.` MUST NOT be url-encoded.\n\nThe URL-encoding may be shown incorrectly in rendered versions due to [OpenAPI 3 not supporting path parameters which contain slashes](https://github.com/OAI/OpenAPI-Specification/issues/892). This may also lead to OpenAPI validators not validating paths containing folders correctly.", + "required": true, + "schema": { + "type": "string" }, - "billing_plan_null": { - "type": "string", - "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be accepted in a *case insensitive* manner.\nBack-ends MUST resolve the billing plan in the following way if billing is supported:\n\n* If a value is given and it is not `null`: Persist the `plan` that has been provided in the request.\n* Otherwise, don't change the billing plan.\n\nBilling plans not on the list of available plans MUST be rejected with\nopenEO error `BillingPlanInvalid`.", - "example": "free", - "nullable": true + "examples": { + "normal": { + "description": "A path without special chars. It describes a file `europe.geojson` in a folder called `borders`.", + "value": "borders/europe.geojson" + }, + "specialchars": { + "description": "A path with special chars. It describes a file `münster.shp` in folders called `europe` and `österreich`.", + "value": "europe/%C3%B6sterreich/m%C3%BCnster.shp" + } + } + } + ], + "get": { + "summary": "Download a file from the workspace", + "operationId": "download-file", + "description": "Offers a file from the user workspace for download. The file is identified by its path relative to the user's root directory.\nIf a folder is specified as path a `FileOperationUnsupported` error MUST be sent as response.", + "tags": [ + "File Storage" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "A file from the workspace.", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } }, - "billing_plan_null_default": { - "type": "string", - "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be accepted in a *case insensitive* manner.\nBack-ends MUST resolve the billing plan in the following way:\n\n* If a non-`null` value is given: Persist the `plan` that has been provided in the request.\n* Otherwise:\n 1. Persist the `default_plan` exposed through `GET /me`, if available.\n 2. Persist the `default_plan` exposed through `GET /`, if available.\n 3. If a single plan is exposed by the back-end, persist it.\n 4. Otherwise, the back-end MUST throw a `BillingPlanMissing` error.\n\nThe resolved plan MUST be persisted permanently, regardless of any \nchanges to the exposed billing plans in `GET /` in the future.\n\nBilling plans not on the list of available plans MUST be rejected with\nopenEO error `BillingPlanInvalid`.", - "example": "free", - "nullable": true, - "default": null + "4XX": { + "$ref": "#/components/responses/client_error_auth" }, - "collection": { - "title": "Collection", - "type": "object", - "required": [ - "stac_version", - "id", - "description", - "license", - "extent", - "links" - ], - "properties": { - "stac_version": { - "$ref": "#/components/schemas/stac_version" - }, - "stac_extensions": { - "$ref": "#/components/schemas/stac_extensions" - }, - "type": { - "type": "string", - "enum": [ - "Collection" - ], - "description": "For STAC versions >= 1.0.0-rc.1 this field is required." - }, - "id": { - "$ref": "#/components/schemas/collection_id" - }, - "title": { + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + }, + "put": { + "summary": "Upload a file to the workspace", + "operationId": "upload-file", + "description": "Uploads a new file to the given path or updates an existing file if a file at the path exists.\n\nFolders are created once required by a file upload. Empty folders can't be created.", + "tags": [ + "File Storage" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "The file has been uploaded successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/file" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + }, + "requestBody": { + "required": true, + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + }, + "delete": { + "summary": "Delete a file from the workspace", + "operationId": "delete-file", + "description": "Deletes an existing user-uploaded file specified by its path. Resulting empty folders MUST be deleted automatically.\n\nBack-ends MAY support deleting folders including its files and sub-folders. If not supported by the back-end a `FileOperationUnsupported` error MUST be sent as response.", + "tags": [ + "File Storage" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "204": { + "description": "The file has been successfully deleted at the back-end." + }, + "4XX": { + "$ref": "#/components/responses/client_error_auth" + }, + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + }, + "/me": { + "get": { + "summary": "Information about the authenticated user", + "operationId": "describe-account", + "description": "Lists information about the authenticated user, e.g. the user id.\nThe endpoint MAY return the disk quota available to the user. The endpoint MAY also return links related to user management and the user profile, e.g. where payments are handled or the user profile could be edited.\nFor back-ends that involve accounting, this service MAY also return the currently available money or credits in the currency the back-end is working with.\nThis endpoint MAY be extended to fulfil the specification of the [OpenID Connect UserInfo Endpoint](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo).", + "tags": [ + "Account Management" + ], + "security": [ + { + "Bearer": [] + } + ], + "responses": { + "200": { + "description": "Information about the logged in user.", + "content": { + "application/json": { + "schema": { + "title": "User Data", + "description": "Holds user information. If no budget or storage limit applies to the user account the corresponding properties MUST be set to null.", + "type": "object", + "required": [ + "user_id" + ], + "properties": { + "user_id": { "type": "string", - "description": "A short descriptive one-line title for the collection." - }, - "description": { + "description": "A unique user identifier specific to the back-end, which could either be chosen by a user or is automatically generated by the back-end during the registration process at the back-end.\nIt is meant to be used as an identifier in URIs (e.g. for sharing purposes), which is primarily used in machine-to-machine communication. Preferrably use the human-readable property `name` to display the user's name in user interfaces instead of the user identifier.", + "pattern": "^[\\w\\-\\.~]+$", + "example": "john_doe" + }, + "name": { "type": "string", - "format": "commonmark", - "description": "Detailed multi-line description to explain the collection.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation." - }, - "keywords": { - "type": "array", - "description": "List of keywords describing the collection.", - "items": { - "type": "string" - } - }, - "version": { + "description": "The user name, a human-friendly displayable name. Could be the user's real name or a nickname." + }, + "default_plan": { "type": "string", - "description": "Version of the collection.\n\nThis property REQUIRES to add `version` (STAC < 1.0.0-rc.1) or\n`https://stac-extensions.github.io/version/v1.2.0/schema.json` (STAC >= 1.0.0-rc.1)\nto the list of `stac_extensions`." - }, - "deprecated": { - "type": "boolean", - "default": false, - "description": "Specifies that the collection is deprecated with the potential to\nbe removed. It should be transitioned out of usage as soon as\npossible and users should refrain from using it in new projects.\n\nA link with relation type `latest-version` SHOULD be added to the\nlinks and MUST refer to the collection that can be used instead.\n\nThis property REQUIRES to add `version` (STAC < 1.0.0-rc.1) or\n`https://stac-extensions.github.io/version/v1.2.0/schema.json` (STAC >= 1.0.0-rc.1)\nto the list of `stac_extensions`." - }, - "license": { - "$ref": "#/components/schemas/stac_license" - }, - "providers": { - "$ref": "#/components/schemas/stac_providers" - }, - "extent": { + "description": "Name of the single plan the user is currently subscribed to if any.", + "example": "free" + }, + "storage": { + "title": "User Storage", + "description": "Information about the storage space available to the user.", "type": "object", - "title": "Collection Extent", - "description": "The extent of the data in the collection. Additional members MAY\nbe added to represent other extents, for example, thermal or\npressure ranges.\n\nThe first item in the array always describes the overall extent of\nthe data. All subsequent items describe more preciseextents,\ne.g. to identify clusters of data.\nClients only interested in the overall extent will only need to\naccess the first item in each array.", + "nullable": true, "required": [ - "spatial", - "temporal" + "free", + "quota" ], "properties": { - "spatial": { - "title": "Collection Spatial Extent", - "description": "The *potential* spatial extents of the features in the collection.", - "type": "object", - "properties": { - "bbox": { - "description": "One or more bounding boxes that describe the spatial extent\nof the dataset.\n\nThe first bounding box describes the overall spatial extent\nof the data. All subsequent bounding boxes describe more\nprecise bounding boxes, e.g. to identify clusters of data.\nClients only interested in the overall spatial extent will\nonly need to access the first item in each array.", - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/bbox" - } - } - } - }, - "temporal": { - "title": "Collection Temporal Extent", - "description": "The *potential* temporal extents of the features in the collection.", - "type": "object", - "properties": { - "interval": { - "description": "One or more time intervals that describe the temporal extent\nof the dataset.\n\nThe first time interval describes the overall temporal extent\nof the data. All subsequent time intervals describe more\nprecise time intervals, e.g. to identify clusters of data.\nClients only interested in the overall extent will only need\nto access the first item in each array.", - "type": "array", - "minItems": 1, - "items": { - "description": "Begin and end times of the time interval. The coordinate\nreference system is the Gregorian calendar.\n\nThe value `null` is supported and indicates an open time\ninterval.", - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { - "type": "string", - "format": "date-time", - "nullable": true - }, - "example": [ - "2011-11-11T12:22:11Z", - null - ] - } - } - } - } + "free": { + "type": "integer", + "description": "Free storage space in bytes, which is still available to the user. Effectively, this is the disk quota minus the used space by the user, e.g. user-uploaded files and job results.", + "example": 536870912 + }, + "quota": { + "type": "integer", + "description": "Maximum storage space (disk quota) in bytes available to the user.", + "example": 1073741824 + } } - }, - "links": { - "description": "Links related to this collection.\nCould reference to licensing information, other meta data formats with\nadditional information or a preview image.\n\nIt is RECOMMENDED to provide links with the following\n`rel` (relation) types:\n\n1. `root` and `parent`: URL to the data discovery endpoint at `/collections`.\n\n2. `license`: A link to the license(s) SHOULD be specified if the `license`\nfield is set to `proprietary` or `various`.\n\n3. `example`: Links to examples of processes that use this collection.\n\n4. `latest-version`: If a collection has been marked as deprecated, a link SHOULD\npoint to the latest version of the collection. The relation types `predecessor-version`\n(link to older version) and `successor-version` (link to newer version) can also be used\nto show the relation between versions.\n\n5. `alternate`: An alternative representation of the collection.\nFor example, this could be the collection available through another\ncatalog service such as OGC CSW, a human-readable HTML version or a\nmetadata document following another standard such as ISO 19115 or DCAT.\n\n6. `http://www.opengis.net/def/rel/ogc/1.0/queryables`: URL to the\nqueryables endpoint at `/collections/{collection_id}/queryables`.\nFor JSON Schema documents, the `type` field must be set to `application/schema+json`.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking)\nand the STAC specification for Collections.", + }, + "budget": { + "type": "number", + "nullable": true, + "description": "The remaining budget a user has available.\nThe value MUST be specified in the currency of the back-end.\nThe value SHOULD be set to `null` if no explicit limit applies." + }, + "links": { + "description": "Links related to the user profile, e.g. where payments\nare handled or the user profile could be edited.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `payment`: A page where users can recharge their user account with money or credits.\n\n2. `edit-form`: Points to a page where the user can edit his user profile.\n\n3. `alternate`: Any other representation of these (and potentially additional)\nuser information, e.g. the (public) user profile page.\nIt is RECOMMENDED to add descriptive titles for a better user experience.\n\n4. `related`: Any other user-specific links to be shown in clients,\ne.g. to user-specific settings, invoices, etc. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", "type": "array", "items": { - "$ref": "#/components/schemas/link" - } - }, - "cube:dimensions": { - "title": "STAC Collection Cube Dimensions", - "description": "The named default dimensions of the data cube.\nNames must be unique per collection.\n\nThe keys of the object are the dimension names. For\ninteroperability, it is RECOMMENDED to use the\nfollowing dimension names if there is only a single\ndimension with the specified criteria:\n\n* `x` for the dimension of type `spatial` with the axis set to `x`\n* `y` for the dimension of type `spatial` with the axis set to `y`\n* `z` for the dimension of type `spatial` with the axis set to `z`\n* `t` for the dimension of type `temporal`\n* `bands` for dimensions of type `bands`\n* `geometry` for dimensions of type `geometry`\n\nThis property REQUIRES to add a version of the data cube extension to the list\nof `stac_extensions`, e.g. `https://stac-extensions.github.io/datacube/v2.2.0/schema.json`.", - "type": "object", - "additionalProperties": { - "x-additionalPropertiesName": "Dimension Name", - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - } - ] - } - }, - "summaries": { - "title": "STAC Summaries (Collection Properties)", - "description": "Collection properties from STAC extensions (e.g. EO,\nSAR, Satellite or Scientific) or even custom extensions.\n\nSummaries are either a unique set of all available\nvalues, statistics *or* a JSON Schema. Statistics only\nspecify the range (minimum and maximum values) by default,\nbut can optionally be accompanied by additional\nstatistical values. The range can specify the\npotential range of values, but it is recommended to be\nas precise as possible. The set of values MUST contain\nat least one element and it is strongly RECOMMENDED to\nlist all values. It is recommended to list as many\nproperties as reasonable so that consumers get a full\noverview of the Collection. Properties that are\ncovered by the Collection specification (e.g.\n`providers` and `license`) SHOULD NOT be repeated in the\nsummaries.\n\nPotential fields for the summaries can be found here:\n\n* **[STAC Common Metadata](https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/common-metadata.md)**:\n A list of commonly used fields throughout all domains\n* **[Content Extensions](https://github.com/radiantearth/stac-spec/blob/v1.0.0/extensions/README.md#list-of-content-extensions)**:\n Domain-specific fields for domains such as EO, SAR and point clouds.\n* **Custom Properties**:\n It is generally allowed to add custom fields.", - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "type": "array", - "title": "Set of values", - "items": { - "description": "A value of any type." - } - }, - { - "$ref": "#/components/schemas/collection_summary_stats" - }, - { - "$ref": "#/components/schemas/json_schema" - } - ] - } - }, - "assets": { - "description": "Dictionary of asset objects for data that can be downloaded,\neach with a unique key.\nThe keys MAY be used by clients as file names.\n\nImplementing this property REQUIRES to add `collection-assets`\nto the list of `stac_extensions` in STAC < 1.0.0-rc.1.", - "allOf": [ - { - "$ref": "#/components/schemas/stac_assets" - } + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "href": "https://openeo.example/john_doe/payment/", + "rel": "payment" + }, + { + "href": "https://openeo.example/john_doe/edit/", + "rel": "edit-form" + }, + { + "href": "https://openeo.example/john_doe/", + "rel": "alternate", + "type": "text/html", + "title": "User profile" + }, + { + "href": "https://openeo.example/john_doe.vcf", + "rel": "alternate", + "type": "text/vcard", + "title": "vCard of John Doe" + }, + { + "href": "https://openeo.example/john_doe/invoices", + "rel": "related", + "type": "text/html", + "title": "Invoices" + } ] + } } + } } + } }, - "stac_version": { - "type": "string", - "description": "The [version of the STAC specification](https://github.com/radiantearth/stac-spec/releases), which MAY not be equal to the [STAC API version](#tag/EO-Data-Discovery/STAC). Supports versions 0.9.x and 1.x.x.", - "pattern": "^(0\\.9.\\d+|1\\.\\d+.\\d+)", - "example": "1.0.0" + "4XX": { + "$ref": "#/components/responses/client_error_auth" }, - "stac_extensions": { - "type": "array", - "description": "A list of implemented STAC extensions. The list contains URLs to the JSON Schema files it can be validated against. For STAC < 1.0.0-rc.1 shortcuts such as `sar` can be used instead of the schema URL.", - "uniqueItems": true, - "items": { - "anyOf": [ - { - "title": "Reference to a JSON Schema", - "type": "string", - "format": "uri", - "example": "https://openeo.example/stac/custom-extemsion/v1.0.0/schema.json" - }, - { - "title": "Reference to a core extension (STAC < 1.0.0-rc.1 only)", - "type": "string", - "example": "datacube" - } - ] - } + "5XX": { + "$ref": "#/components/responses/server_error" + } + } + } + } + }, + "components": { + "schemas": { + "conformsTo": { + "description": "Lists all conformance classes specified in various standards that the\nimplementation conforms to. Conformance classes are commonly used in\nall OGC APIs and the STAC API specification.\n\nThe general openEO conformance class is `https://api.openeo.org/1.2.0`.\nSee the individual openEO API extensions for their conformance classes.\n\nThis property is REQUIRED for STAC API versions 1.0.0-beta.1 and later.", + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "example": [ + "https://api.openeo.org/1.2.0", + "https://api.openeo.org/extensions/commercial-data/0.1.0", + "https://api.openeo.org/extensions/federation/0.1.0", + "https://api.stacspec.org/v1.0.0/collections" + ] + }, + "udf_runtime": { + "type": "object", + "required": [ + "type", + "default" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/object_title" }, - "stac_license": { - "type": "string", - "description": "License(s) of the data as a SPDX [License identifier](https://spdx.org/licenses/).\nAlternatively, use `proprietary` if the license is not on the SPDX\nlicense list or `various` if multiple licenses apply. In these two cases\nlinks to the license texts SHOULD be added, see the `license` link\nrelation type.\n\nNon-SPDX licenses SHOULD add a link to the license text with the\n`license` relation in the links section. The license text MUST NOT be\nprovided as a value of this field. If there is no public license URL\navailable, it is RECOMMENDED to host the license text and link to it.", - "example": "Apache-2.0" + "description": { + "$ref": "#/components/schemas/description" }, - "stac_providers": { - "type": "array", - "description": "A list of providers, which MAY include all organizations capturing or processing the data or the hosting provider. Providers SHOULD be listed in chronological order with the most recent provider being the last element of the list.", - "items": { + "type": { + "type": "string", + "description": "The type of the UDF runtime.\n\nPredefined types are:\n* `language` for Programming Languages and\n* `docker` for Docker Containers.\n\nThe types can potentially be extended by back-ends." + }, + "default": { + "type": "string" + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "links": { + "type": "array", + "description": "Links related to this runtime, e.g. external documentation.\n\nIt is highly RECOMMENDED to provide at least links with\nthe following `rel` (relation) types:\n\n1. `about`: A resource that further explains the runtime,\ne.g. a user guide or the documentation. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } + } + }, + "discriminator": { + "propertyName": "type", + "mapping": { + "language": "#/components/schemas/udf_programming_language", + "docker": "#/components/schemas/udf_docker" + } + } + }, + "udf_programming_language": { + "allOf": [ + { + "$ref": "#/components/schemas/udf_runtime" + }, + { + "title": "Programming language", + "required": [ + "versions" + ], + "properties": { + "default": { + "type": "string", + "description": "The default version. MUST be one of the keys in the `versions` object." + }, + "versions": { + "title": "Programming language versions", + "description": "Versions available for the programming language.", + "type": "object", + "additionalProperties": { + "x-additionalPropertiesName": "Programming Language Version", + "title": "Programming language version", "type": "object", - "title": "Provider", "required": [ - "name" + "libraries" ], "properties": { - "name": { - "description": "The name of the organization or the individual.", - "type": "string", - "example": "Example Cloud Corp." - }, - "description": { - "description": "Multi-line description to add further provider information such as processing details for processors and producers, hosting details for hosts or basic contact information.\n\nCommonMark 0.29 syntax MAY be used for rich text representation.", - "type": "string", - "example": "No further processing applied." - }, - "roles": { - "description": "Roles of the provider.\n\nThe provider's role(s) can be one or more of the following\nelements:\n* `licensor`: The organization that is licensing the dataset under\nthe license specified in the collection's license field.\n* `producer`: The producer of the data is the provider that\ninitially captured and processed the source data, e.g. ESA for\nSentinel-2 data.\n* `processor`: A processor is any provider who processed data to a\nderived product.\n* `host`: The host is the actual provider offering the data on their\nstorage. There SHOULD be no more than one host, specified as last\nelement of the list.", - "type": "array", - "items": { - "type": "string", - "enum": [ - "producer", - "licensor", - "processor", - "host" - ] + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "libraries": { + "description": "Map of installed libraries, modules, packages or extensions for the programming language. The names of them are used as the property keys.", + "additionalProperties": { + "x-additionalPropertiesName": "Library Name", + "title": "Programming language library", + "type": "object", + "required": [ + "version" + ], + "properties": { + "version": { + "type": "string", + "description": "Version number of the library." }, - "example": [ - "producer", - "licensor", - "host" - ] - }, - "url": { - "description": "Homepage on which the provider describes the dataset and publishes contact information.", - "type": "string", - "format": "uri", - "example": "https://cloud.example" + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "links": { + "type": "array", + "description": "Additional links related to this library,\ne.g. external documentation for this library.\n\nIt is highly RECOMMENDED to provide links with\nthe following `rel` (relation) types:\n\n1. `about`: A resource that further explains the library,\ne.g. a user guide or the documentation. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\n2. `latest-version`: If a library has been marked as deprecated,\na link SHOULD point to either a new library replacing the deprecated\nlibrary or a latest version of the library available at the back-end.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } + } + } } + } } + } } + } + } + ] + }, + "udf_docker": { + "allOf": [ + { + "$ref": "#/components/schemas/udf_runtime" }, - "stac_assets": { - "type": "object", - "title": "Assets", - "description": "Dictionary of asset objects for data that can be downloaded, each with a\nunique key. The keys MAY be used by clients as file names.", - "additionalProperties": { - "$ref": "#/components/schemas/asset" + { + "title": "Docker container", + "required": [ + "docker", + "tags" + ], + "properties": { + "docker": { + "type": "string", + "description": "Identifier of a Docker image on Docker Hub or a private repository, which can run openEO UDFs. This is what is used in the `docker pull` command excluding the tag, e.g. `php`, `mcr.microsoft.com/dotnet/runtime` or `myregistry.local:5000/testing/test-image`." }, - "example": { - "preview.png": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/preview.png", - "type": "image/png", - "title": "Thumbnail", - "roles": [ - "thumbnail" - ] - }, - "process.json": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/process.json", - "type": "application/json", - "title": "Original Process", - "roles": [ - "process", - "reproduction" - ] - }, - "1.tif": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/1.tif", - "type": "image/tiff; application=geotiff", - "title": "Band 1", - "roles": [ - "data" - ] - }, - "2.tif": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/2.tif", - "type": "image/tiff; application=geotiff", - "title": "Band 2", - "roles": [ - "data" - ] - }, - "inspire.xml": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/inspire.xml", - "type": "application/xml", - "title": "INSPIRE metadata", - "description": "INSPIRE compliant XML metadata", - "roles": [ - "metadata" - ] - } + "default": { + "type": "string", + "description": "The default tag. MUST be one of the values in the `tags` array." + }, + "tags": { + "type": "array", + "description": "The docker tags that are supported.", + "minItems": 1, + "items": { + "type": "string" + } } + } + } + ] + }, + "result_status": { + "type": "string", + "enum": [ + "running", + "canceled", + "finished", + "error" + ], + "description": "The status of a batch job.\n\nThis field is REQUIRED if the `partial` parameter is given.\nThis field is strongly RECOMMENDED if the job has stopped due to an error.", + "default": "finished" + }, + "batch_job_result": { + "title": "Batch Job Results Response as STAC Item", + "description": "The STAC specification should be the main guidance for implementing this.\nSpecifying the `bbox` is strongly RECOMMENDED for STAC compliance, but can be omitted if the result is unlocated and the `geometry` is set to `null`.", + "type": "object", + "required": [ + "stac_version", + "id", + "type", + "geometry", + "properties", + "assets", + "links" + ], + "properties": { + "stac_version": { + "$ref": "#/components/schemas/stac_version" }, - "collection_summary_stats": { - "type": "object", - "title": "Statistics / Range", - "description": "By default, only ranges with a minimum and a maximum value can be specified. Ranges can be specified for ordinal values only, which means they need to have a rank order. Therefore, ranges can only be specified for numbers and some special types of strings. Examples: grades (A to F), dates or times. Implementors are free to add other derived statistical values to the object, for example `mean` or `stddev`.", - "required": [ - "minimum", - "maximum" - ], - "properties": { - "minimum": { - "description": "The minimum value (inclusive).", - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - }, - "maximum": { - "description": "The maximum value (inclusive).", - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - } + "stac_extensions": { + "$ref": "#/components/schemas/stac_extensions" + }, + "id": { + "$ref": "#/components/schemas/job_id" + }, + "type": { + "type": "string", + "description": "The GeoJSON type that applies to this metadata document, which MUST always be a \"Feature\" according to the STAC specification.\nThis type does **not** describe the spatial data type of the assets.", + "enum": [ + "Feature" + ] }, "bbox": { - "description": "Each bounding box is provided as four or six numbers,\ndepending on whether the coordinate reference system\nincludes a vertical axis (height or depth):\n\n* West (lower left corner, coordinate axis 1)\n* South (lower left corner, coordinate axis 2)\n* Base (optional, minimum value, coordinate axis 3)\n* East (upper right corner, coordinate axis 1)\n* North (upper right corner, coordinate axis 2)\n* Height (optional, maximum value, coordinate axis 3)\n\nThe coordinate reference system of the values is WGS 84\nlongitude/latitude (http://www.opengis.net/def/crs/OGC/1.3/CRS84).\n\nFor WGS 84 longitude/latitude the values are in most cases\nthe sequence of minimum longitude, minimum latitude, maximum\nlongitude and maximum latitude.\n\nHowever, in cases where the box spans the antimeridian the\nfirst value (west-most box edge) is larger than the third value\n(east-most box edge).\n\nIf the vertical axis is included, the third and the sixth\nnumber are the bottom and the top of the 3-dimensional bounding box.", - "type": "array", - "oneOf": [ - { - "title": "4 elements", - "minItems": 4, - "maxItems": 4 - }, - { - "title": "6 elements", - "minItems": 6, - "maxItems": 6 - } - ], - "items": { - "type": "number" - }, - "example": [ - -180, - -90, - 180, - 90 - ] + "$ref": "#/components/schemas/bbox" }, - "collection_id": { - "type": "string", - "description": "A unique identifier for the collection, which MUST match the specified pattern.", - "pattern": "^[\\w\\-\\.~\\/]+$", - "example": "Sentinel-2A" + "geometry": { + "description": "Defines the full footprint of the asset represented by this item as\nGeoJSON Geometry.\n\nResults without a known location can set this value to `null`.", + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + } + ], + "example": { + "type": "Polygon", + "coordinates": [ + [ + [ + -180, + -90 + ], + [ + 180, + -90 + ], + [ + 180, + 90 + ], + [ + -180, + 90 + ], + [ + -180, + -90 + ] + ] + ] + } }, - "dimension": { - "title": "Dimension", - "description": "A dimension, each object represents a distinct dimension with the key being the dimension name.", - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "description": "Type of the dimension.", - "type": "string", - "enum": [ - "spatial", - "temporal", - "bands", - "geometry", - "other" - ] - }, - "description": { - "$ref": "#/components/schemas/description" - } + "properties": { + "type": "object", + "title": "Item Properties", + "description": "MAY contain additional properties other than the required property `datetime`, e.g. custom properties or properties from the STAC specification or STAC extensions.", + "required": [ + "datetime" + ], + "additionalProperties": true, + "properties": { + "datetime": { + "title": "Date and Time", + "description": "The searchable date/time of the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.\n\nIf this field is set to `null` (usually for larger time ranges), it is STRONGLY RECOMMENDED to specify both `start_datetime` and `end_datetime` for STAC compliance.", + "type": "string", + "format": "date-time", + "nullable": true }, - "discriminator": { - "propertyName": "type", - "mapping": { - "spatial": "#/components/schemas/dimension_spatial", - "temporal": "#/components/schemas/dimension_temporal", - "bands": "#/components/schemas/dimension_bands", - "geometry": "#/components/schemas/dimension_geometry", - "other": "#/components/schemas/dimension_other" - } + "start_datetime": { + "type": "string", + "format": "date-time", + "description": "For time series: The first or start date and time for the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." + }, + "end_datetime": { + "type": "string", + "format": "date-time", + "description": "For time series: The last or end date and time for the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." + }, + "title": { + "$ref": "#/components/schemas/eo_title" + }, + "description": { + "$ref": "#/components/schemas/eo_description" + }, + "license": { + "$ref": "#/components/schemas/stac_license" + }, + "providers": { + "$ref": "#/components/schemas/stac_providers" + }, + "created": { + "$ref": "#/components/schemas/created" + }, + "updated": { + "$ref": "#/components/schemas/updated" + }, + "expires": { + "type": "string", + "format": "date-time", + "description": "Time until which the assets are accessible, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2020-11-01T00:00:00Z" + }, + "openeo:status": { + "$ref": "#/components/schemas/result_status" } + } }, - "dimension_other": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Additional Dimension", - "type": "object", - "properties": { - "extent": { - "$ref": "#/components/schemas/collection_dimension_extent_open" - }, - "values": { - "$ref": "#/components/schemas/collection_dimension_values" - }, - "step": { - "$ref": "#/components/schemas/collection_dimension_step" - }, - "unit": { - "$ref": "#/components/schemas/collection_dimension_unit" - }, - "reference_system": { - "description": "The reference system for the dimension.", - "type": "string" - } - } - } - ] - }, - "dimension_geometry": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Geometry Dimension", - "type": "object", - "required": [ - "bbox" - ], - "properties": { - "axes": { - "description": "Axes of the vector dimension as an ordered set of `x`, `y` and `z`. Defaults to `x` and `y`.", - "default": [ - "x", - "y" - ], - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/dimension_axis_xyz" - } - }, - "bbox": { - "$ref": "#/components/schemas/bbox" - }, - "values": { - "description": "Optionally, a representation of the vectors. This can be a list of WKT string or other free-form identifiers.", - "type": "array", - "items": { - "type": "string" - } - }, - "geometry_types": { - "description": "A set of all geometry types included in this dimension. If not present, mixed geometry types must be assumed.", - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/geometry_type" - } - }, - "reference_system": { - "$ref": "#/components/schemas/collection_dimension_srs" - } - } - } - ] + "assets": { + "$ref": "#/components/schemas/stac_assets" }, - "dimension_bands": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Band Dimension", - "description": "A dimension for the bands.\n\nThe band dimension only specifies the band names\nas dimension labels. Further information to the\nbands are available in either `sar:bands` or\n`eo:bands` in the `summaries` property.", - "type": "object", - "required": [ - "values" - ], - "properties": { - "values": { - "$ref": "#/components/schemas/collection_dimension_values" - } - } - } - ] + "links": { + "type": "array", + "description": "Links related to this batch job result, e.g. a link to an \ninvoice, additional log files or external documentation.\n\nThe links MUST NOT contain links to the processed and\ndownloadable data. Instead specify these in the `assets` property.\nClients MUST NOT download the data referenced in the links by\ndefault.\n\nIt is **strongly recommended** to add a link with relation type\n`canonical`, which points to this STAC document using a signed URL.\nThis way the STAC metadata can be used by non-openEO clients\nwithout additional authentication steps.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "rel": "canonical", + "type": "application/geo+json", + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item.json" + } + ] + } + } + }, + "file_format": { + "x-additionalPropertiesName": "File Format Name", + "title": "File Format", + "type": "object", + "description": "Describes a specific file format.", + "required": [ + "gis_data_types", + "parameters" + ], + "properties": { + "title": { + "$ref": "#/components/schemas/object_title" }, - "dimension_spatial": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Spatial Dimension", - "description": "A spatial (raster) dimension in one of the horizontal (x or y) or vertical (z) directions.", - "type": "object", - "required": [ - "axis" - ], - "properties": { - "axis": { - "$ref": "#/components/schemas/dimension_axis_xyz" - }, - "extent": { - "description": "Extent (lower and upper bounds) of the dimension as two-dimensional array. Open intervals with `null` are not allowed.", - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { - "type": "number" - } - }, - "values": { - "description": "A set of all potential values.", - "type": "array", - "minItems": 1, - "items": { - "type": "number" - } - }, - "step": { - "$ref": "#/components/schemas/collection_dimension_step" - }, - "reference_system": { - "$ref": "#/components/schemas/collection_dimension_srs" - } - }, - "discriminator": { - "propertyName": "axis", - "mapping": { - "x": "#/components/schemas/dimension_spatial_horizontal", - "y": "#/components/schemas/dimension_spatial_horizontal", - "z": "#/components/schemas/dimension_spatial_vertical" - } - } - } - ] + "description": { + "$ref": "#/components/schemas/description" }, - "dimension_axis_xyz": { - "title": "Axis", - "description": "Axis of a geometry or dimension (`x`, `y` or `z`)", + "gis_data_types": { + "type": "array", + "description": "Specifies the supported GIS spatial data types for this format.\nIt is RECOMMENDED to specify at least one of the data types, which will likely become a requirement in a future API version.", + "items": { "type": "string", "enum": [ - "x", - "y", - "z" + "raster", + "vector", + "table", + "pointcloud", + "other" ] + } }, - "dimension_spatial_horizontal": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension_spatial" - }, - { - "title": "Horizontal Spatial Dimension", - "required": [ - "extent" - ] - } - ] + "deprecated": { + "$ref": "#/components/schemas/deprecated" }, - "dimension_spatial_vertical": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension_spatial" - }, - { - "title": "Vertical Spatial Dimension", - "anyOf": [ - { - "title": "Vertical Spatial Dimension with Extent", - "required": [ - "extent" - ] - }, - { - "title": "Vertical Spatial Dimension with Values", - "required": [ - "values" - ] - } + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "parameters": { + "title": "File Format Parameters", + "description": "Specifies the supported parameters for this file format.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/resource_parameter" + } + }, + "links": { + "type": "array", + "description": "Links related to this file format, e.g. external documentation.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } + } + } + }, + "production": { + "type": "boolean", + "description": "Specifies whether the implementation is ready to be used in production use (`true`) or not (`false`).\nClients SHOULD only connect to non-production implementations if the user explicitly confirmed to use a non-production implementation.\nThis flag is part of `GET /.well-known/openeo` and `GET /`. It MUST be used consistently in both endpoints.", + "default": false + }, + "links_pagination": { + "description": "Links related to this list of resources, for example links for pagination\nor alternative formats such as a human-readable HTML version.\nThe links array MUST NOT be paginated.\n\nIf pagination is implemented, the following `rel` (relation) types apply:\n\n1. `next` (REQUIRED): A link to the next page, except on the last page.\n\n2. `prev` (OPTIONAL): A link to the previous page, except on the first page.\n\n3. `first` (OPTIONAL): A link to the first page, except on the first page.\n\n4. `last` (OPTIONAL): A link to the last page, except on the last page.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + } + }, + "link": { + "title": "Link", + "description": "A link to another resource on the web. Bases on [RFC 5899](https://www.rfc-editor.org/rfc/rfc5988.html).", + "type": "object", + "required": [ + "href", + "rel" + ], + "properties": { + "rel": { + "type": "string", + "description": "Relationship between the current document and the linked document. SHOULD be a [registered link relation type](https://www.iana.org/assignments/link-relations/link-relations.xml) whenever feasible.", + "example": "related" + }, + "href": { + "type": "string", + "description": "The value MUST be a valid URL.", + "format": "uri", + "example": "https://openeo.example" + }, + "type": { + "type": "string", + "description": "The value MUST be a string that hints at the format used to represent data at the provided URI, preferably a media (MIME) type.", + "example": "text/html" + }, + "title": { + "type": "string", + "description": "Used as a human-readable label for a link.", + "example": "openEO" + } + } + }, + "asset": { + "title": "STAC Asset", + "type": "object", + "required": [ + "href" + ], + "properties": { + "href": { + "title": "Asset location", + "description": "URL to the downloadable asset.\nThe URLs SHOULD be available without authentication so that external clients can download them easily. If the data is confidential, signed URLs SHOULD be used to protect against unauthorized access from third parties.", + "type": "string" + }, + "title": { + "description": "The displayed title for clients and users.", + "type": "string" + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "Multi-line description to explain the asset.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich\ntext representation." + }, + "type": { + "title": "Media Type", + "description": "Media type of the asset.", + "type": "string", + "example": "image/tiff; application=geotiff" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Purposes of the asset. Can be any value, but commonly used values are:\n\n* `thumbnail`: A visualization of the data, usually a lower-resolution true color image in JPEG or PNG format.\n* `reproducibility`: Information how the data was produced and/or can be reproduced, e.g. the process graph used to compute the data in JSON format.\n* `data`: The computed data in the format specified by the user in the process graph (applicable in `GET /jobs/{job_id}/results` only).\n* `metadata`: Additional metadata available for the computed data.", + "example": [ + "data" + ] + } + } + }, + "money": { + "description": "An amount of money or credits. The value MUST be specified in the currency the back-end is working with. The currency can be retrieved by calling `GET /`. If no currency is set, this field MUST be `null`.", + "type": "number", + "minimum": 0, + "example": 12.98, + "nullable": true, + "default": null + }, + "budget": { + "type": "number", + "minimum": 0, + "nullable": true, + "description": "Maximum amount of costs the request is allowed to produce.\nThe value MUST be specified in the currency of the back-end.\nNo limits apply, if the value is `null` or the back-end has no currency\nset in `GET /`.", + "example": 100, + "default": null + }, + "budget_update": { + "type": "number", + "minimum": 0, + "nullable": true, + "description": "Maximum amount of costs the request is allowed to produce.\nThe value MUST be specified in the currency of the back-end.\nNo limits apply, if the value is `null`.", + "example": 100 + }, + "billing_plan": { + "type": "string", + "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be handled in a *case insensitive* manner.\n\nThe plans can be retrieved from `GET /`, but the value returned here may\nnot be in the list of plans any longer.", + "example": "free" + }, + "billing_plan_null": { + "type": "string", + "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be accepted in a *case insensitive* manner.\nBack-ends MUST resolve the billing plan in the following way if billing is supported:\n\n* If a value is given and it is not `null`: Persist the `plan` that has been provided in the request.\n* Otherwise, don't change the billing plan.\n\nBilling plans not on the list of available plans MUST be rejected with\nopenEO error `BillingPlanInvalid`.", + "example": "free", + "nullable": true + }, + "billing_plan_null_default": { + "type": "string", + "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be accepted in a *case insensitive* manner.\nBack-ends MUST resolve the billing plan in the following way:\n\n* If a non-`null` value is given: Persist the `plan` that has been provided in the request.\n* Otherwise:\n 1. Persist the `default_plan` exposed through `GET /me`, if available.\n 2. Persist the `default_plan` exposed through `GET /`, if available.\n 3. If a single plan is exposed by the back-end, persist it.\n 4. Otherwise, the back-end MUST throw a `BillingPlanMissing` error.\n\nThe resolved plan MUST be persisted permanently, regardless of any \nchanges to the exposed billing plans in `GET /` in the future.\n\nBilling plans not on the list of available plans MUST be rejected with\nopenEO error `BillingPlanInvalid`.", + "example": "free", + "nullable": true, + "default": null + }, + "collection": { + "title": "Collection", + "type": "object", + "required": [ + "stac_version", + "id", + "description", + "license", + "extent", + "links" + ], + "properties": { + "stac_version": { + "$ref": "#/components/schemas/stac_version" + }, + "stac_extensions": { + "$ref": "#/components/schemas/stac_extensions" + }, + "type": { + "type": "string", + "enum": [ + "Collection" + ], + "description": "For STAC versions >= 1.0.0-rc.1 this field is required." + }, + "id": { + "$ref": "#/components/schemas/collection_id" + }, + "title": { + "type": "string", + "description": "A short descriptive one-line title for the collection." + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "Detailed multi-line description to explain the collection.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation." + }, + "keywords": { + "type": "array", + "description": "List of keywords describing the collection.", + "items": { + "type": "string" + } + }, + "version": { + "type": "string", + "description": "Version of the collection.\n\nThis property REQUIRES to add `version` (STAC < 1.0.0-rc.1) or\n`https://stac-extensions.github.io/version/v1.2.0/schema.json` (STAC >= 1.0.0-rc.1)\nto the list of `stac_extensions`." + }, + "deprecated": { + "type": "boolean", + "default": false, + "description": "Specifies that the collection is deprecated with the potential to\nbe removed. It should be transitioned out of usage as soon as\npossible and users should refrain from using it in new projects.\n\nA link with relation type `latest-version` SHOULD be added to the\nlinks and MUST refer to the collection that can be used instead.\n\nThis property REQUIRES to add `version` (STAC < 1.0.0-rc.1) or\n`https://stac-extensions.github.io/version/v1.2.0/schema.json` (STAC >= 1.0.0-rc.1)\nto the list of `stac_extensions`." + }, + "license": { + "$ref": "#/components/schemas/stac_license" + }, + "providers": { + "$ref": "#/components/schemas/stac_providers" + }, + "extent": { + "type": "object", + "title": "Collection Extent", + "description": "The extent of the data in the collection. Additional members MAY\nbe added to represent other extents, for example, thermal or\npressure ranges.\n\nThe first item in the array always describes the overall extent of\nthe data. All subsequent items describe more preciseextents,\ne.g. to identify clusters of data.\nClients only interested in the overall extent will only need to\naccess the first item in each array.", + "required": [ + "spatial", + "temporal" + ], + "properties": { + "spatial": { + "title": "Collection Spatial Extent", + "description": "The *potential* spatial extents of the features in the collection.", + "type": "object", + "properties": { + "bbox": { + "description": "One or more bounding boxes that describe the spatial extent\nof the dataset.\n\nThe first bounding box describes the overall spatial extent\nof the data. All subsequent bounding boxes describe more\nprecise bounding boxes, e.g. to identify clusters of data.\nClients only interested in the overall spatial extent will\nonly need to access the first item in each array.", + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/bbox" + } + } + } + }, + "temporal": { + "title": "Collection Temporal Extent", + "description": "The *potential* temporal extents of the features in the collection.", + "type": "object", + "properties": { + "interval": { + "description": "One or more time intervals that describe the temporal extent\nof the dataset.\n\nThe first time interval describes the overall temporal extent\nof the data. All subsequent time intervals describe more\nprecise time intervals, e.g. to identify clusters of data.\nClients only interested in the overall extent will only need\nto access the first item in each array.", + "type": "array", + "minItems": 1, + "items": { + "description": "Begin and end times of the time interval. The coordinate\nreference system is the Gregorian calendar.\n\nThe value `null` is supported and indicates an open time\ninterval.", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "example": [ + "2011-11-11T12:22:11Z", + null ] + } } - ] + } + } + } }, - "dimension_temporal": { + "links": { + "description": "Links related to this collection.\nCould reference to licensing information, other meta data formats with\nadditional information or a preview image.\n\nIt is RECOMMENDED to provide links with the following\n`rel` (relation) types:\n\n1. `root` and `parent`: URL to the data discovery endpoint at `/collections`.\n\n2. `license`: A link to the license(s) SHOULD be specified if the `license`\nfield is set to `proprietary` or `various`.\n\n3. `example`: Links to examples of processes that use this collection.\n\n4. `latest-version`: If a collection has been marked as deprecated, a link SHOULD\npoint to the latest version of the collection. The relation types `predecessor-version`\n(link to older version) and `successor-version` (link to newer version) can also be used\nto show the relation between versions.\n\n5. `alternate`: An alternative representation of the collection.\nFor example, this could be the collection available through another\ncatalog service such as OGC CSW, a human-readable HTML version or a\nmetadata document following another standard such as ISO 19115 or DCAT.\n\n6. `http://www.opengis.net/def/rel/ogc/1.0/queryables`: URL to the\nqueryables endpoint at `/collections/{collection_id}/queryables`.\nFor JSON Schema documents, the `type` field must be set to `application/schema+json`.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking)\nand the STAC specification for Collections.", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + } + }, + "cube:dimensions": { + "title": "STAC Collection Cube Dimensions", + "description": "The named default dimensions of the data cube.\nNames must be unique per collection.\n\nThe keys of the object are the dimension names. For\ninteroperability, it is RECOMMENDED to use the\nfollowing dimension names if there is only a single\ndimension with the specified criteria:\n\n* `x` for the dimension of type `spatial` with the axis set to `x`\n* `y` for the dimension of type `spatial` with the axis set to `y`\n* `z` for the dimension of type `spatial` with the axis set to `z`\n* `t` for the dimension of type `temporal`\n* `bands` for dimensions of type `bands`\n* `geometry` for dimensions of type `geometry`\n\nThis property REQUIRES to add a version of the data cube extension to the list\nof `stac_extensions`, e.g. `https://stac-extensions.github.io/datacube/v2.2.0/schema.json`.", + "type": "object", + "additionalProperties": { + "x-additionalPropertiesName": "Dimension Name", "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Temporal Dimension", - "description": "A temporal dimension based on the ISO 8601 standard. The temporal reference system for the data is expected to be ISO 8601 compliant (Gregorian calendar / UTC). Data not compliant with ISO 8601 can be represented as an *Additional Dimension Object* with `type` set to `temporal`.", - "type": "object", - "required": [ - "extent" - ], - "properties": { - "values": { - "description": "If the dimension consists of set of specific values they can be listed here. The dates and/or times MUST be strings compliant to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601).", - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - }, - "extent": { - "description": "Extent (lower and upper bounds) of the dimension as two-dimensional array. The dates and/or times MUST be strings compliant to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601). `null` is allowed for open date ranges.", - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { - "type": "string", - "nullable": true - } - }, - "step": { - "description": "The space between the temporal instances as [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations), e.g. `P1D`. Use `null` for irregularly spaced steps.", - "type": "string", - "nullable": true - } - } - } + { + "$ref": "#/components/schemas/dimension" + } ] + } }, - "collection_dimension_srs": { - "title": "Spatial reference system", - "description": "The spatial reference system for the data, specified as [EPSG code](http://www.epsg-registry.org/), [WKT2 (ISO 19162) string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html), [PROJJSON object](https://proj.org/specifications/projjson.html) or [PROJ definition (deprecated)](https://proj.org/usage/quickstart.html). Defaults to EPSG code 4326.", - "default": 4326, + "summaries": { + "title": "STAC Summaries (Collection Properties)", + "description": "Collection properties from STAC extensions (e.g. EO,\nSAR, Satellite or Scientific) or even custom extensions.\n\nSummaries are either a unique set of all available\nvalues, statistics *or* a JSON Schema. Statistics only\nspecify the range (minimum and maximum values) by default,\nbut can optionally be accompanied by additional\nstatistical values. The range can specify the\npotential range of values, but it is recommended to be\nas precise as possible. The set of values MUST contain\nat least one element and it is strongly RECOMMENDED to\nlist all values. It is recommended to list as many\nproperties as reasonable so that consumers get a full\noverview of the Collection. Properties that are\ncovered by the Collection specification (e.g.\n`providers` and `license`) SHOULD NOT be repeated in the\nsummaries.\n\nPotential fields for the summaries can be found here:\n\n* **[STAC Common Metadata](https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/common-metadata.md)**:\n A list of commonly used fields throughout all domains\n* **[Content Extensions](https://github.com/radiantearth/stac-spec/blob/v1.0.0/extensions/README.md#list-of-content-extensions)**:\n Domain-specific fields for domains such as EO, SAR and point clouds.\n* **Custom Properties**:\n It is generally allowed to add custom fields.", + "type": "object", + "additionalProperties": { "oneOf": [ - { - "type": "number", - "title": "EPSG code" - }, - { - "type": "string", - "title": "WKT2 or PROJ definition (deprecated)" - }, - { - "type": "object", - "title": "PROJJSON" - } + { + "type": "array", + "title": "Set of values", + "items": { + "description": "A value of any type." + } + }, + { + "$ref": "#/components/schemas/collection_summary_stats" + }, + { + "$ref": "#/components/schemas/json_schema" + } ] + } }, - "collection_dimension_extent_open": { - "description": "If the dimension consists of [ordinal](https://en.wikipedia.org/wiki/Level_of_measurement#Ordinal_scale) values, the extent (lower and upper bounds) of the values as two-dimensional array. Use `null` for open intervals.", - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { - "type": "number", - "nullable": true + "assets": { + "description": "Dictionary of asset objects for data that can be downloaded,\neach with a unique key.\nThe keys MAY be used by clients as file names.\n\nImplementing this property REQUIRES to add `collection-assets`\nto the list of `stac_extensions` in STAC < 1.0.0-rc.1.", + "allOf": [ + { + "$ref": "#/components/schemas/stac_assets" } - }, - "collection_dimension_values": { - "description": "A set of all potential values, especially useful for [nominal](https://en.wikipedia.org/wiki/Level_of_measurement#Nominal_level) values.\n\n**Important:** The order of the values MUST be exactly how the dimension values are also ordered in the data (cube). If the values specify band names, the values MUST be in the same order as they are in the corresponding band fields (i.e. `eo:bands` or `sar:bands`).", + ] + } + } + }, + "stac_version": { + "type": "string", + "description": "The [version of the STAC specification](https://github.com/radiantearth/stac-spec/releases), which MAY not be equal to the [STAC API version](#tag/EO-Data-Discovery/STAC). Supports versions 0.9.x and 1.x.x.", + "pattern": "^(0\\.9.\\d+|1\\.\\d+.\\d+)", + "example": "1.0.0" + }, + "stac_extensions": { + "type": "array", + "description": "A list of implemented STAC extensions. The list contains URLs to the JSON Schema files it can be validated against. For STAC < 1.0.0-rc.1 shortcuts such as `sar` can be used instead of the schema URL.", + "uniqueItems": true, + "items": { + "anyOf": [ + { + "title": "Reference to a JSON Schema", + "type": "string", + "format": "uri", + "example": "https://openeo.example/stac/custom-extemsion/v1.0.0/schema.json" + }, + { + "title": "Reference to a core extension (STAC < 1.0.0-rc.1 only)", + "type": "string", + "example": "datacube" + } + ] + } + }, + "stac_license": { + "type": "string", + "description": "License(s) of the data as a SPDX [License identifier](https://spdx.org/licenses/).\nAlternatively, use `proprietary` if the license is not on the SPDX\nlicense list or `various` if multiple licenses apply. In these two cases\nlinks to the license texts SHOULD be added, see the `license` link\nrelation type.\n\nNon-SPDX licenses SHOULD add a link to the license text with the\n`license` relation in the links section. The license text MUST NOT be\nprovided as a value of this field. If there is no public license URL\navailable, it is RECOMMENDED to host the license text and link to it.", + "example": "Apache-2.0" + }, + "stac_providers": { + "type": "array", + "description": "A list of providers, which MAY include all organizations capturing or processing the data or the hosting provider. Providers SHOULD be listed in chronological order with the most recent provider being the last element of the list.", + "items": { + "type": "object", + "title": "Provider", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "The name of the organization or the individual.", + "type": "string", + "example": "Example Cloud Corp." + }, + "description": { + "description": "Multi-line description to add further provider information such as processing details for processors and producers, hosting details for hosts or basic contact information.\n\nCommonMark 0.29 syntax MAY be used for rich text representation.", + "type": "string", + "example": "No further processing applied." + }, + "roles": { + "description": "Roles of the provider.\n\nThe provider's role(s) can be one or more of the following\nelements:\n* `licensor`: The organization that is licensing the dataset under\nthe license specified in the collection's license field.\n* `producer`: The producer of the data is the provider that\ninitially captured and processed the source data, e.g. ESA for\nSentinel-2 data.\n* `processor`: A processor is any provider who processed data to a\nderived product.\n* `host`: The host is the actual provider offering the data on their\nstorage. There SHOULD be no more than one host, specified as last\nelement of the list.", "type": "array", - "minItems": 1, "items": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] - } + "type": "string", + "enum": [ + "producer", + "licensor", + "processor", + "host" + ] + }, + "example": [ + "producer", + "licensor", + "host" + ] + }, + "url": { + "description": "Homepage on which the provider describes the dataset and publishes contact information.", + "type": "string", + "format": "uri", + "example": "https://cloud.example" + } + } + } + }, + "stac_assets": { + "type": "object", + "title": "Assets", + "description": "Dictionary of asset objects for data that can be downloaded, each with a\nunique key. The keys MAY be used by clients as file names.", + "additionalProperties": { + "$ref": "#/components/schemas/asset" + }, + "example": { + "preview.png": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/preview.png", + "type": "image/png", + "title": "Thumbnail", + "roles": [ + "thumbnail" + ] }, - "collection_dimension_step": { - "description": "If the dimension consists of [interval](https://en.wikipedia.org/wiki/Level_of_measurement#Interval_scale) values, the space between the values. Use `null` for irregularly spaced steps.", - "type": "number", - "nullable": true + "process.json": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/process.json", + "type": "application/json", + "title": "Original Process", + "roles": [ + "process", + "reproduction" + ] }, - "collection_dimension_unit": { - "description": "The unit of measurement for the data, preferably compliant to [UDUNITS-2](https://ncics.org/portfolio/other-resources/udunits2/) units (singular).", - "type": "string" + "1.tif": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/1.tif", + "type": "image/tiff; application=geotiff", + "title": "Band 1", + "roles": [ + "data" + ] }, - "process_arguments": { - "title": "Process Arguments", - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/process_argument_value" - } + "2.tif": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/2.tif", + "type": "image/tiff; application=geotiff", + "title": "Band 2", + "roles": [ + "data" + ] }, - "process_argument_value": { - "title": "Process Argument Value", - "description": "Arguments for a process. See the API documentation for more information.", - "nullable": true, - "anyOf": [ - { - "type": "object", - "nullable": true, - "title": "Object (restricted)", - "properties": { - "from_parameter": { - "not": {} - }, - "from_node": { - "not": {} - }, - "process_graph": { - "not": {} - } - } - }, - { - "type": "string", - "title": "String" - }, - { - "type": "number", - "title": "Number (incl. integers)" - }, - { - "type": "boolean", - "title": "Boolean" - }, - { - "type": "array", - "title": "Array", - "items": { - "$ref": "#/components/schemas/process_argument_value" - } - }, - { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - { - "type": "object", - "title": "Result Reference", - "description": "Data that is expected to be passed from another process.", - "required": [ - "from_node" - ], - "properties": { - "from_node": { - "description": "The ID of the node that data is expected to come from.", - "type": "string" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "title": "Parameter Reference", - "description": "A parameter for a process graph. Data that is expected to be passed to a process graph either from the user directly or from the process that is executing the process graph.", - "required": [ - "from_parameter" - ], - "properties": { - "from_parameter": { - "description": "The name of the parameter that data is expected to come from.", - "type": "string" - } - }, - "additionalProperties": false - } - ] - }, - "process_graph": { - "title": "Process Graph", - "description": "A process graph defines a graph-like structure as a connected set of executable processes. Each key is a unique identifier (node ID) that is used to refer to the process in the graph.", - "type": "object", - "additionalProperties": { - "x-additionalPropertiesName": "Node ID", - "title": "Process Node", - "type": "object", - "required": [ - "process_id", - "arguments" - ], - "properties": { - "process_id": { - "$ref": "#/components/schemas/process_id" - }, - "namespace": { - "$ref": "#/components/schemas/process_namespace" - }, - "result": { - "type": "boolean", - "description": "Used to specify which node is the last in the chain and returns the result to return to the requesting context. This flag MUST only be set once in each list of process nodes.", - "default": false - }, - "description": { - "description": "Optional description about the process and its arguments.", - "type": "string", - "nullable": true - }, - "arguments": { - "$ref": "#/components/schemas/process_arguments" - } - } + "inspire.xml": { + "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/inspire.xml", + "type": "application/xml", + "title": "INSPIRE metadata", + "description": "INSPIRE compliant XML metadata", + "roles": [ + "metadata" + ] + } + } + }, + "collection_summary_stats": { + "type": "object", + "title": "Statistics / Range", + "description": "By default, only ranges with a minimum and a maximum value can be specified. Ranges can be specified for ordinal values only, which means they need to have a rank order. Therefore, ranges can only be specified for numbers and some special types of strings. Examples: grades (A to F), dates or times. Implementors are free to add other derived statistical values to the object, for example `mean` or `stddev`.", + "required": [ + "minimum", + "maximum" + ], + "properties": { + "minimum": { + "description": "The minimum value (inclusive).", + "anyOf": [ + { + "type": "string" }, - "example": { - "dc": { - "process_id": "load_collection", - "arguments": { - "id": "Sentinel-2", - "spatial_extent": { - "west": 16.1, - "east": 16.6, - "north": 48.6, - "south": 47.2 - }, - "temporal_extent": [ - "2018-01-01", - "2018-02-01" - ] - } - }, - "bands": { - "process_id": "filter_bands", - "description": "Filter and order the bands. The order is important for the following reduce operation.", - "arguments": { - "data": { - "from_node": "dc" - }, - "bands": [ - "B08", - "B04", - "B02" - ] - } - }, - "evi": { - "process_id": "reduce", - "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", - "arguments": { - "data": { - "from_node": "bands" - }, - "dimension": "bands", - "reducer": { - "process_graph": { - "nir": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" - }, - "index": 0 - } - }, - "red": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" - }, - "index": 1 - } - }, - "blue": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" - }, - "index": 2 - } - }, - "sub": { - "process_id": "subtract", - "arguments": { - "data": [ - { - "from_node": "nir" - }, - { - "from_node": "red" - } - ] - } - }, - "p1": { - "process_id": "product", - "arguments": { - "data": [ - 6, - { - "from_node": "red" - } - ] - } - }, - "p2": { - "process_id": "product", - "arguments": { - "data": [ - -7.5, - { - "from_node": "blue" - } - ] - } - }, - "sum": { - "process_id": "sum", - "arguments": { - "data": [ - 1, - { - "from_node": "nir" - }, - { - "from_node": "p1" - }, - { - "from_node": "p2" - } - ] - } - }, - "div": { - "process_id": "divide", - "arguments": { - "data": [ - { - "from_node": "sub" - }, - { - "from_node": "sum" - } - ] - } - }, - "p3": { - "process_id": "product", - "arguments": { - "data": [ - 2.5, - { - "from_node": "div" - } - ] - }, - "result": true - } - } - } - } - }, - "mintime": { - "process_id": "reduce", - "description": "Compute a minimum time composite by reducing the temporal dimension", - "arguments": { - "data": { - "from_node": "evi" - }, - "dimension": "temporal", - "reducer": { - "process_graph": { - "min": { - "process_id": "min", - "arguments": { - "data": { - "from_parameter": "data" - } - }, - "result": true - } - } - } - } - }, - "save": { - "process_id": "save_result", - "arguments": { - "data": { - "from_node": "mintime" - }, - "format": "GTiff" - }, - "result": true - } + { + "type": "number" } + ] }, - "process": { - "title": "Process", - "type": "object", - "properties": { - "id": { - "$ref": "#/components/schemas/process_id" - }, - "summary": { - "$ref": "#/components/schemas/process_summary" - }, - "description": { - "$ref": "#/components/schemas/process_description" - }, - "categories": { - "$ref": "#/components/schemas/process_categories" - }, - "parameters": { - "$ref": "#/components/schemas/process_parameters" - }, - "returns": { - "$ref": "#/components/schemas/process_return_value" - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "exceptions": { - "$ref": "#/components/schemas/process_exceptions" - }, - "examples": { - "type": "array", - "description": "Examples, may be used for unit tests.", - "items": { - "title": "Process Example", - "type": "object", - "required": [ - "arguments" - ], - "properties": { - "title": { - "type": "string", - "description": "A title for the example." - }, - "description": { - "$ref": "#/components/schemas/process_description" - }, - "arguments": { - "$ref": "#/components/schemas/process_arguments" - }, - "returns": { - "description": "The return value which can by of any data type." - } - } - } - }, - "links": { - "type": "array", - "description": "Links related to this process, e.g. additional external documentation.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `latest-version`: If a process has been marked as deprecated, a link SHOULD\npoint to the preferred version of the process. The relation types `predecessor-version`\n(link to older version) and `successor-version` (link to newer version) can also be used\nto show the relation between versions.\n\n2. `example`: Links to examples of other processes that use this process.\n\n3. `cite-as`: For all DOIs associated with the process, the respective DOI\nlinks SHOULD be added.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - }, - "process_graph": { - "$ref": "#/components/schemas/process_graph" - } + "maximum": { + "description": "The maximum value (inclusive).", + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" } + ] + } + } + }, + "bbox": { + "description": "Each bounding box is provided as four or six numbers,\ndepending on whether the coordinate reference system\nincludes a vertical axis (height or depth):\n\n* West (lower left corner, coordinate axis 1)\n* South (lower left corner, coordinate axis 2)\n* Base (optional, minimum value, coordinate axis 3)\n* East (upper right corner, coordinate axis 1)\n* North (upper right corner, coordinate axis 2)\n* Height (optional, maximum value, coordinate axis 3)\n\nThe coordinate reference system of the values is WGS 84\nlongitude/latitude (http://www.opengis.net/def/crs/OGC/1.3/CRS84).\n\nFor WGS 84 longitude/latitude the values are in most cases\nthe sequence of minimum longitude, minimum latitude, maximum\nlongitude and maximum latitude.\n\nHowever, in cases where the box spans the antimeridian the\nfirst value (west-most box edge) is larger than the third value\n(east-most box edge).\n\nIf the vertical axis is included, the third and the sixth\nnumber are the bottom and the top of the 3-dimensional bounding box.", + "type": "array", + "oneOf": [ + { + "title": "4 elements", + "minItems": 4, + "maxItems": 4 }, - "user_defined_process_meta": { - "title": "User-defined Process Metadata", - "description": "A user-defined process, may only contain metadata and no process graph.", - "type": "object", - "required": [ - "id" - ], - "properties": { - "summary": { - "type": "string", - "nullable": true - }, - "description": { - "type": "string", - "nullable": true - }, - "parameters": { - "type": "array", - "nullable": true - }, - "returns": { - "type": "object", - "nullable": true - } + { + "title": "6 elements", + "minItems": 6, + "maxItems": 6 + } + ], + "items": { + "type": "number" + }, + "example": [ + -180, + -90, + 180, + 90 + ] + }, + "collection_id": { + "type": "string", + "description": "A unique identifier for the collection, which MUST match the specified pattern.", + "pattern": "^[\\w\\-\\.~\\/]+$", + "example": "Sentinel-2A" + }, + "dimension": { + "title": "Dimension", + "description": "A dimension, each object represents a distinct dimension with the key being the dimension name.", + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "description": "Type of the dimension.", + "type": "string", + "enum": [ + "spatial", + "temporal", + "bands", + "geometry", + "other" + ] + }, + "description": { + "$ref": "#/components/schemas/description" + } + }, + "discriminator": { + "propertyName": "type", + "mapping": { + "spatial": "#/components/schemas/dimension_spatial", + "temporal": "#/components/schemas/dimension_temporal", + "bands": "#/components/schemas/dimension_bands", + "geometry": "#/components/schemas/dimension_geometry", + "other": "#/components/schemas/dimension_other" + } + } + }, + "dimension_other": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" + }, + { + "title": "Additional Dimension", + "type": "object", + "properties": { + "extent": { + "$ref": "#/components/schemas/collection_dimension_extent_open" }, - "allOf": [ - { - "$ref": "#/components/schemas/process" - } - ] + "values": { + "$ref": "#/components/schemas/collection_dimension_values" + }, + "step": { + "$ref": "#/components/schemas/collection_dimension_step" + }, + "unit": { + "$ref": "#/components/schemas/collection_dimension_unit" + }, + "reference_system": { + "description": "The reference system for the dimension.", + "type": "string" + } + } + } + ] + }, + "dimension_geometry": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" }, - "process_graph_with_metadata": { - "title": "Process Graph with metadata", - "description": "A process graph, optionally enriched with process metadata.", - "type": "object", - "required": [ - "process_graph" - ], - "properties": { - "id": { - "type": "string", - "nullable": true - }, - "summary": { - "type": "string", - "nullable": true - }, - "description": { - "type": "string", - "nullable": true - }, - "parameters": { - "type": "array", - "nullable": true - }, - "returns": { - "type": "object", - "nullable": true - } + { + "title": "Geometry Dimension", + "type": "object", + "required": [ + "bbox" + ], + "properties": { + "axes": { + "description": "Axes of the vector dimension as an ordered set of `x`, `y` and `z`. Defaults to `x` and `y`.", + "default": [ + "x", + "y" + ], + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/dimension_axis_xyz" + } }, - "allOf": [ - { - "$ref": "#/components/schemas/process" - } - ] + "bbox": { + "$ref": "#/components/schemas/bbox" + }, + "values": { + "description": "Optionally, a representation of the vectors. This can be a list of WKT string or other free-form identifiers.", + "type": "array", + "items": { + "type": "string" + } + }, + "geometry_types": { + "description": "A set of all geometry types included in this dimension. If not present, mixed geometry types must be assumed.", + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/geometry_type" + } + }, + "reference_system": { + "$ref": "#/components/schemas/collection_dimension_srs" + } + } + } + ] + }, + "dimension_bands": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" }, - "process_namespace": { - "type": "string", - "nullable": true, - "default": null, - "example": null, - "description": "The namespace the `process_id` is valid for.\n\nThe following options are predefined by the openEO API, but additional\nnamespaces may be introduced by back-ends or in a future version of the API.\n\n* `null` (default): Checks both user-defined and predefined processes,\n but prefers user-defined processes if both are available.\n This allows users to add missing predefined processes for portability,\n e.g. common processes from [processes.openeo.org](https://processes.openeo.org)\n that have a process graph included.\n It is RECOMMENDED to log the namespace selected by the back-end for debugging purposes.\n* `backend`: Uses exclusively the predefined processes listed at `GET /processes`.\n* `user`: Uses exclusively the user-defined processes listed at `GET /process_graphs`.\n\nIf multiple processes with the same identifier exist, Clients SHOULD\ninform the user that it's recommended to select a namespace." + { + "title": "Band Dimension", + "description": "A dimension for the bands.\n\nThe band dimension only specifies the band names\nas dimension labels. Further information to the\nbands are available in either `sar:bands` or\n`eo:bands` in the `summaries` property.", + "type": "object", + "required": [ + "values" + ], + "properties": { + "values": { + "$ref": "#/components/schemas/collection_dimension_values" + } + } + } + ] + }, + "dimension_spatial": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" }, - "process_id": { - "type": "string", - "description": "The identifier for the process. It MUST be unique across its namespace\n(e.g. predefined processes or user-defined processes).\n\nClients SHOULD warn the user if a user-defined process is added with the \nsame identifier as one of the predefined process.", - "pattern": "^\\w+$", - "example": "ndvi" + { + "title": "Spatial Dimension", + "description": "A spatial (raster) dimension in one of the horizontal (x or y) or vertical (z) directions.", + "type": "object", + "required": [ + "axis" + ], + "properties": { + "axis": { + "$ref": "#/components/schemas/dimension_axis_xyz" + }, + "extent": { + "description": "Extent (lower and upper bounds) of the dimension as two-dimensional array. Open intervals with `null` are not allowed.", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "number" + } + }, + "values": { + "description": "A set of all potential values.", + "type": "array", + "minItems": 1, + "items": { + "type": "number" + } + }, + "step": { + "$ref": "#/components/schemas/collection_dimension_step" + }, + "reference_system": { + "$ref": "#/components/schemas/collection_dimension_srs" + } + }, + "discriminator": { + "propertyName": "axis", + "mapping": { + "x": "#/components/schemas/dimension_spatial_horizontal", + "y": "#/components/schemas/dimension_spatial_horizontal", + "z": "#/components/schemas/dimension_spatial_vertical" + } + } + } + ] + }, + "dimension_axis_xyz": { + "title": "Axis", + "description": "Axis of a geometry or dimension (`x`, `y` or `z`)", + "type": "string", + "enum": [ + "x", + "y", + "z" + ] + }, + "dimension_spatial_horizontal": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension_spatial" }, - "process_summary": { - "type": "string", - "description": "A short summary of what the process does." + { + "title": "Horizontal Spatial Dimension", + "required": [ + "extent" + ] + } + ] + }, + "dimension_spatial_vertical": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension_spatial" }, - "process_categories": { - "type": "array", - "description": "A list of categories.", - "items": { + { + "title": "Vertical Spatial Dimension", + "anyOf": [ + { + "title": "Vertical Spatial Dimension with Extent", + "required": [ + "extent" + ] + }, + { + "title": "Vertical Spatial Dimension with Values", + "required": [ + "values" + ] + } + ] + } + ] + }, + "dimension_temporal": { + "allOf": [ + { + "$ref": "#/components/schemas/dimension" + }, + { + "title": "Temporal Dimension", + "description": "A temporal dimension based on the ISO 8601 standard. The temporal reference system for the data is expected to be ISO 8601 compliant (Gregorian calendar / UTC). Data not compliant with ISO 8601 can be represented as an *Additional Dimension Object* with `type` set to `temporal`.", + "type": "object", + "required": [ + "extent" + ], + "properties": { + "values": { + "description": "If the dimension consists of set of specific values they can be listed here. The dates and/or times MUST be strings compliant to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601).", + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "extent": { + "description": "Extent (lower and upper bounds) of the dimension as two-dimensional array. The dates and/or times MUST be strings compliant to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601). `null` is allowed for open date ranges.", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { "type": "string", - "description": "Name of the category." + "nullable": true + } + }, + "step": { + "description": "The space between the temporal instances as [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations), e.g. `P1D`. Use `null` for irregularly spaced steps.", + "type": "string", + "nullable": true } + } + } + ] + }, + "collection_dimension_srs": { + "title": "Spatial reference system", + "description": "The spatial reference system for the data, specified as [EPSG code](http://www.epsg-registry.org/), [WKT2 (ISO 19162) string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html), [PROJJSON object](https://proj.org/specifications/projjson.html) or [PROJ definition (deprecated)](https://proj.org/usage/quickstart.html). Defaults to EPSG code 4326.", + "default": 4326, + "oneOf": [ + { + "type": "number", + "title": "EPSG code" }, - "process_return_value": { - "type": "object", - "title": "Process Return Value", - "description": "Description of the data that is returned by this process.", - "required": [ - "schema" - ], - "properties": { - "description": { - "$ref": "#/components/schemas/process_description" - }, - "schema": { - "$ref": "#/components/schemas/process_schema" - } + { + "type": "string", + "title": "WKT2 or PROJ definition (deprecated)" + }, + { + "type": "object", + "title": "PROJJSON" + } + ] + }, + "collection_dimension_extent_open": { + "description": "If the dimension consists of [ordinal](https://en.wikipedia.org/wiki/Level_of_measurement#Ordinal_scale) values, the extent (lower and upper bounds) of the values as two-dimensional array. Use `null` for open intervals.", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "number", + "nullable": true + } + }, + "collection_dimension_values": { + "description": "A set of all potential values, especially useful for [nominal](https://en.wikipedia.org/wiki/Level_of_measurement#Nominal_level) values.\n\n**Important:** The order of the values MUST be exactly how the dimension values are also ordered in the data (cube). If the values specify band names, the values MUST be in the same order as they are in the corresponding band fields (i.e. `eo:bands` or `sar:bands`).", + "type": "array", + "minItems": 1, + "items": { + "oneOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + } + }, + "collection_dimension_step": { + "description": "If the dimension consists of [interval](https://en.wikipedia.org/wiki/Level_of_measurement#Interval_scale) values, the space between the values. Use `null` for irregularly spaced steps.", + "type": "number", + "nullable": true + }, + "collection_dimension_unit": { + "description": "The unit of measurement for the data, preferably compliant to [UDUNITS-2](https://ncics.org/portfolio/other-resources/udunits2/) units (singular).", + "type": "string" + }, + "process_arguments": { + "title": "Process Arguments", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/process_argument_value" + } + }, + "process_argument_value": { + "title": "Process Argument Value", + "description": "Arguments for a process. See the API documentation for more information.", + "nullable": true, + "anyOf": [ + { + "type": "object", + "nullable": true, + "title": "Object (restricted)", + "properties": { + "from_parameter": { + "not": {} + }, + "from_node": { + "not": {} + }, + "process_graph": { + "not": {} } + } }, - "experimental": { - "type": "boolean", - "description": "Declares that the specified entity is experimental, which means that it is likely to change or may produce unpredictable behaviour. Users should refrain from using it in production, but still feel encouraged to try it out and give feedback.", - "default": false + { + "type": "string", + "title": "String" }, - "deprecated": { + { + "type": "number", + "title": "Number (incl. integers)" + }, + { + "type": "boolean", + "title": "Boolean" + }, + { + "type": "array", + "title": "Array", + "items": { + "$ref": "#/components/schemas/process_argument_value" + } + }, + { + "$ref": "#/components/schemas/process_graph_with_metadata" + }, + { + "type": "object", + "title": "Result Reference", + "description": "Data that is expected to be passed from another process.", + "required": [ + "from_node" + ], + "properties": { + "from_node": { + "description": "The ID of the node that data is expected to come from.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "title": "Parameter Reference", + "description": "A parameter for a process graph. Data that is expected to be passed to a process graph either from the user directly or from the process that is executing the process graph.", + "required": [ + "from_parameter" + ], + "properties": { + "from_parameter": { + "description": "The name of the parameter that data is expected to come from.", + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "process_graph": { + "title": "Process Graph", + "description": "A process graph defines a graph-like structure as a connected set of executable processes. Each key is a unique identifier (node ID) that is used to refer to the process in the graph.", + "type": "object", + "additionalProperties": { + "x-additionalPropertiesName": "Node ID", + "title": "Process Node", + "type": "object", + "required": [ + "process_id", + "arguments" + ], + "properties": { + "process_id": { + "$ref": "#/components/schemas/process_id" + }, + "namespace": { + "$ref": "#/components/schemas/process_namespace" + }, + "result": { "type": "boolean", - "description": "Declares that the specified entity is deprecated with the potential\nto be removed in any of the next versions. It should be transitioned out\nof usage as soon as possible and users should refrain from using it in\nnew implementations.", + "description": "Used to specify which node is the last in the chain and returns the result to return to the requesting context. This flag MUST only be set once in each list of process nodes.", "default": false + }, + "description": { + "description": "Optional description about the process and its arguments.", + "type": "string", + "nullable": true + }, + "arguments": { + "$ref": "#/components/schemas/process_arguments" + } + } + }, + "example": { + "dc": { + "process_id": "load_collection", + "arguments": { + "id": "Sentinel-2", + "spatial_extent": { + "west": 16.1, + "east": 16.6, + "north": 48.6, + "south": 47.2 + }, + "temporal_extent": [ + "2018-01-01", + "2018-02-01" + ] + } }, - "process_exceptions": { - "type": "object", - "title": "Process Exceptions", - "description": "Declares exceptions (errors) that might occur during execution\nof this process. This list is just for informative purposes and may be\nincomplete. This list MUST only contain exceptions that stop the\nexecution of a process and MUST NOT contain warnings, notices or\ndebugging messages. It is meant to primarily contain errors that\nhave been caused by the user. It is RECOMMENDED that exceptions\nare referred to and explained in process or parameter descriptions.\n\nThe keys define the error code and MUST match the following pattern:\n`^\\w+$`\n\nThis schema follows the schema of the general openEO error list (see\nerrors.json).", - "additionalProperties": { - "x-additionalPropertiesName": "Error Code", - "title": "Process Exception", - "type": "object", - "required": [ - "message" - ], - "properties": { - "description": { - "type": "string", - "format": "commonmark", - "description": "Detailed description to explain the error to client\nusers and back-end developers. This should not be shown in the\nclients directly, but MAY be linked to in the errors `url`\nproperty.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used\nfor rich text representation." + "bands": { + "process_id": "filter_bands", + "description": "Filter and order the bands. The order is important for the following reduce operation.", + "arguments": { + "data": { + "from_node": "dc" + }, + "bands": [ + "B08", + "B04", + "B02" + ] + } + }, + "evi": { + "process_id": "reduce", + "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", + "arguments": { + "data": { + "from_node": "bands" + }, + "dimension": "bands", + "reducer": { + "process_graph": { + "nir": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" }, - "message": { - "type": "string", - "description": "Explains the reason the server is rejecting the request. This message is intended to be displayed to the client user. For \"4xx\" error codes the message SHOULD explain shortly how the client needs to modify the request.\n\nThe message MAY contain variables, which are enclosed by curly brackets. Example: `{variable_name}`", - "example": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}" + "index": 0 + } + }, + "red": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" }, - "http": { - "type": "integer", - "description": "HTTP Status Code, following the [error handling conventions in openEO](#section/API-Principles/Error-Handling). Defaults to `400`.", - "default": 400 - } + "index": 1 + } + }, + "blue": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 2 + } + }, + "sub": { + "process_id": "subtract", + "arguments": { + "data": [ + { + "from_node": "nir" + }, + { + "from_node": "red" + } + ] + } + }, + "p1": { + "process_id": "product", + "arguments": { + "data": [ + 6, + { + "from_node": "red" + } + ] + } + }, + "p2": { + "process_id": "product", + "arguments": { + "data": [ + -7.5, + { + "from_node": "blue" + } + ] + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_node": "nir" + }, + { + "from_node": "p1" + }, + { + "from_node": "p2" + } + ] + } + }, + "div": { + "process_id": "divide", + "arguments": { + "data": [ + { + "from_node": "sub" + }, + { + "from_node": "sum" + } + ] + } + }, + "p3": { + "process_id": "product", + "arguments": { + "data": [ + 2.5, + { + "from_node": "div" + } + ] + }, + "result": true } + } } + } }, - "process_parameters": { - "type": "array", - "description": "A list of parameters.\n\nThe order in the array corresponds to the parameter order to\nbe used in clients that don't support named parameters.\n\n**Note:** Specifying an empty array is different from (if allowed)\n`null` or the property being absent.\nAn empty array means the process has no parameters.\n`null` / property absent means that the parameters are unknown as\nthe user has not specified them. There could still be parameters in the\nprocess graph, if one is specified.", - "items": { - "$ref": "#/components/schemas/process_parameter" - } - }, - "base_parameter": { - "type": "object", - "required": [ - "name", - "description" - ], - "properties": { - "name": { - "type": "string", - "description": "A unique name for the parameter. \n\nIt is RECOMMENDED to use [snake case](https://en.wikipedia.org/wiki/Snake_case) (e.g. `window_size` or `scale_factor`).", - "pattern": "^\\w+$" - }, - "description": { - "$ref": "#/components/schemas/process_description" - }, - "optional": { - "type": "boolean", - "description": "Determines whether this parameter is optional to be specified even when no default is specified.\nClients SHOULD automatically set this parameter to `true`, if a default value is specified. Back-ends SHOULD NOT fail, if a default value is specified and this flag is missing.", - "default": false - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "default": { - "description": "The default value for this parameter. Required parameters SHOULD NOT specify a default value. Optional parameters SHOULD always specify a default value." + "mintime": { + "process_id": "reduce", + "description": "Compute a minimum time composite by reducing the temporal dimension", + "arguments": { + "data": { + "from_node": "evi" + }, + "dimension": "temporal", + "reducer": { + "process_graph": { + "min": { + "process_id": "min", + "arguments": { + "data": { + "from_parameter": "data" + } + }, + "result": true } + } } + } }, - "parameter": { - "title": "Parameter", - "type": "object", - "required": [ - "schema" - ], - "properties": { - "schema": { - "$ref": "#/components/schemas/data_type_schema" - } + "save": { + "process_id": "save_result", + "arguments": { + "data": { + "from_node": "mintime" }, - "allOf": [ - { - "$ref": "#/components/schemas/base_parameter" - } - ] + "format": "GTiff" + }, + "result": true + } + } + }, + "process": { + "title": "Process", + "type": "object", + "properties": { + "id": { + "$ref": "#/components/schemas/process_id" }, - "process_parameter": { - "title": "Process Parameter", - "type": "object", - "required": [ - "schema" - ], - "properties": { - "schema": { - "$ref": "#/components/schemas/process_schema" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/base_parameter" - } - ] + "summary": { + "$ref": "#/components/schemas/process_summary" + }, + "description": { + "$ref": "#/components/schemas/process_description" + }, + "categories": { + "$ref": "#/components/schemas/process_categories" + }, + "parameters": { + "$ref": "#/components/schemas/process_parameters" }, - "batch_job": { - "title": "Batch Job", - "description": "The metadata of a batch jobs that has been submitted by the authenticated user.", + "returns": { + "$ref": "#/components/schemas/process_return_value" + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + }, + "experimental": { + "$ref": "#/components/schemas/experimental" + }, + "exceptions": { + "$ref": "#/components/schemas/process_exceptions" + }, + "examples": { + "type": "array", + "description": "Examples, may be used for unit tests.", + "items": { + "title": "Process Example", "type": "object", "required": [ - "id", - "status", - "created" + "arguments" ], "properties": { - "id": { - "$ref": "#/components/schemas/job_id" - }, - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "status": { - "type": "string", - "enum": [ - "created", - "queued", - "running", - "canceled", - "finished", - "error" - ], - "description": "The current status of a batch job.\n\nThe following status changes can occur:\n* `POST /jobs`: The status is initialized as `created`.\n* `POST /jobs/{job_id}/results`: The status is set to `queued`, if\nprocessing doesn't start instantly.\n * Once the processing starts the status is set to `running`.\n * Once the data is available to download the status is set to `finished`.\n * Whenever an error occurs during processing, the status MUST be set to `error`.\n* `DELETE /jobs/{job_id}/results`: The status is set to `canceled` if\nthe status was `running` beforehand and partial or preliminary results\nare available to be downloaded. Otherwise the status is set to\n`created`. ", - "example": "running", - "default": "created" - }, - "progress": { - "type": "number", - "description": "Indicates the process of a running batch job in percent.\nCan also be set for a job which stopped due to an error or was canceled by the user. In this case, the value indicates the progress at which the job stopped. The Property may not be available for the status codes `created` and `queued`.\nSubmitted and queued jobs only allow the value `0`, finished jobs only allow the value `100`.", - "minimum": 0, - "maximum": 100, - "example": 75.5 - }, - "created": { - "$ref": "#/components/schemas/created" - }, - "updated": { - "$ref": "#/components/schemas/updated" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan" - }, - "costs": { - "$ref": "#/components/schemas/money" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "usage": { - "description": "Metrics about the resource usage of the batch job.\n\nBack-ends are not expected to update the metrics while processing data,\nso the metrics can only be available after the job has finished\nor has stopped due to an error.\nFor usage metrics during processing, metrics can better be added to the\nlogs (e.g. `GET /jobs/{job_id}/logs`) with the same schema.", - "allOf": [ - { - "$ref": "#/components/schemas/usage" - } - ] - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - }, - "links": { - "type": "array", - "description": "Links related to this batch job, e.g. a links to \ninvoices, log files or results.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `monitor`: If logs are available, a link to the [logs endpoint](#tag/Batch-Jobs/operation/debug-job).\n2. `result`: If batch job results are available, a link to the [results endpoint](#tag/Batch-Jobs/operation/list-results).\n\nThe relation types `monitor` and `result` may occur for various batch job states:\n\n1. `created`: When the batch job was executed before and has been reset to `created` after an\n [update](#tag/Batch-Jobs/operation/update-job) there could still be results and logs available\n until they get discarded by [queueing the batch job again](#tag/Batch-Jobs/operation/start-job).\n2. `finished`: The full log and results are expected to be available.\n3. `error` / `canceled`: Partial results and logs may be available.\n\nFor more relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "rel": "result", - "type": "application/json", - "title": "Batch Job Results", - "href": "https://openeo.example/api/v1/jobs/123/logs" - }, - { - "rel": "result", - "type": "application/json", - "title": "Batch Job Logs", - "href": "https://openeo.example/api/v1/jobs/123/logs" - } - ] - } + "title": { + "type": "string", + "description": "A title for the example." + }, + "description": { + "$ref": "#/components/schemas/process_description" + }, + "arguments": { + "$ref": "#/components/schemas/process_arguments" + }, + "returns": { + "description": "The return value which can by of any data type." + } } + } }, - "job_id": { - "type": "string", - "description": "Per-backend unique identifier of the batch job, generated by the back-end during creation. MUST match the specified pattern.", - "pattern": "^[\\w\\-\\.~]+$", - "example": "a3cca2b2aa1e3b5b" + "links": { + "type": "array", + "description": "Links related to this process, e.g. additional external documentation.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `latest-version`: If a process has been marked as deprecated, a link SHOULD\npoint to the preferred version of the process. The relation types `predecessor-version`\n(link to older version) and `successor-version` (link to newer version) can also be used\nto show the relation between versions.\n\n2. `example`: Links to examples of other processes that use this process.\n\n3. `cite-as`: For all DOIs associated with the process, the respective DOI\nlinks SHOULD be added.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + } }, - "created": { - "type": "string", - "format": "date-time", - "description": "Date and time of creation, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2017-01-01T09:32:12Z" + "process_graph": { + "$ref": "#/components/schemas/process_graph" + } + } + }, + "user_defined_process_meta": { + "title": "User-defined Process Metadata", + "description": "A user-defined process, may only contain metadata and no process graph.", + "type": "object", + "required": [ + "id" + ], + "properties": { + "summary": { + "type": "string", + "nullable": true }, - "updated": { - "type": "string", - "format": "date-time", - "description": "Date and time of the last status change, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2017-01-01T09:36:18Z" + "description": { + "type": "string", + "nullable": true + }, + "parameters": { + "type": "array", + "nullable": true + }, + "returns": { + "type": "object", + "nullable": true + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/process" + } + ] + }, + "process_graph_with_metadata": { + "title": "Process Graph with metadata", + "description": "A process graph, optionally enriched with process metadata.", + "type": "object", + "required": [ + "process_graph" + ], + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "summary": { + "type": "string", + "nullable": true }, "description": { - "type": "string", - "format": "commonmark", - "description": "Detailed description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation." + "type": "string", + "nullable": true }, - "object_title": { - "type": "string", - "description": "A human-readable short title to be displayed to users **in addition** to the names specified in the keys. This property is only for better user experience so that users can understand the names better. Example titles could be `GeoTiff` for the key `GTiff` (for file formats) or `OGC Web Map Service` for the key `WMS` (for service types). The title MUST NOT be used in communication (e.g. in process graphs), although clients MAY translate the titles into the corresponding names." + "parameters": { + "type": "array", + "nullable": true }, - "eo_title": { - "description": "A short description to easily distinguish entities.", - "type": "string", - "nullable": true, - "example": "NDVI based on Sentinel 2" + "returns": { + "type": "object", + "nullable": true + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/process" + } + ] + }, + "process_namespace": { + "type": "string", + "nullable": true, + "default": null, + "example": null, + "description": "The namespace the `process_id` is valid for.\n\nThe following options are predefined by the openEO API, but additional\nnamespaces may be introduced by back-ends or in a future version of the API.\n\n* `null` (default): Checks both user-defined and predefined processes,\n but prefers user-defined processes if both are available.\n This allows users to add missing predefined processes for portability,\n e.g. common processes from [processes.openeo.org](https://processes.openeo.org)\n that have a process graph included.\n It is RECOMMENDED to log the namespace selected by the back-end for debugging purposes.\n* `backend`: Uses exclusively the predefined processes listed at `GET /processes`.\n* `user`: Uses exclusively the user-defined processes listed at `GET /process_graphs`.\n\nIf multiple processes with the same identifier exist, Clients SHOULD\ninform the user that it's recommended to select a namespace." + }, + "process_id": { + "type": "string", + "description": "The identifier for the process. It MUST be unique across its namespace\n(e.g. predefined processes or user-defined processes).\n\nClients SHOULD warn the user if a user-defined process is added with the \nsame identifier as one of the predefined process.", + "pattern": "^\\w+$", + "example": "ndvi" + }, + "process_summary": { + "type": "string", + "description": "A short summary of what the process does." + }, + "process_categories": { + "type": "array", + "description": "A list of categories.", + "items": { + "type": "string", + "description": "Name of the category." + } + }, + "process_return_value": { + "type": "object", + "title": "Process Return Value", + "description": "Description of the data that is returned by this process.", + "required": [ + "schema" + ], + "properties": { + "description": { + "$ref": "#/components/schemas/process_description" }, - "eo_description": { + "schema": { + "$ref": "#/components/schemas/process_schema" + } + } + }, + "experimental": { + "type": "boolean", + "description": "Declares that the specified entity is experimental, which means that it is likely to change or may produce unpredictable behaviour. Users should refrain from using it in production, but still feel encouraged to try it out and give feedback.", + "default": false + }, + "deprecated": { + "type": "boolean", + "description": "Declares that the specified entity is deprecated with the potential\nto be removed in any of the next versions. It should be transitioned out\nof usage as soon as possible and users should refrain from using it in\nnew implementations.", + "default": false + }, + "process_exceptions": { + "type": "object", + "title": "Process Exceptions", + "description": "Declares exceptions (errors) that might occur during execution\nof this process. This list is just for informative purposes and may be\nincomplete. This list MUST only contain exceptions that stop the\nexecution of a process and MUST NOT contain warnings, notices or\ndebugging messages. It is meant to primarily contain errors that\nhave been caused by the user. It is RECOMMENDED that exceptions\nare referred to and explained in process or parameter descriptions.\n\nThe keys define the error code and MUST match the following pattern:\n`^\\w+$`\n\nThis schema follows the schema of the general openEO error list (see\nerrors.json).", + "additionalProperties": { + "x-additionalPropertiesName": "Error Code", + "title": "Process Exception", + "type": "object", + "required": [ + "message" + ], + "properties": { + "description": { "type": "string", "format": "commonmark", - "description": "Detailed multi-line description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", - "nullable": true, - "example": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2" - }, - "process_description": { + "description": "Detailed description to explain the error to client\nusers and back-end developers. This should not be shown in the\nclients directly, but MAY be linked to in the errors `url`\nproperty.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used\nfor rich text representation." + }, + "message": { "type": "string", - "format": "commonmark", - "description": "Detailed description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. In addition to the CommonMark syntax, clients can convert process IDs that are formatted as in the following example into links instead of code blocks: ``` ``process_id()`` ```" + "description": "Explains the reason the server is rejecting the request. This message is intended to be displayed to the client user. For \"4xx\" error codes the message SHOULD explain shortly how the client needs to modify the request.\n\nThe message MAY contain variables, which are enclosed by curly brackets. Example: `{variable_name}`", + "example": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}" + }, + "http": { + "type": "integer", + "description": "HTTP Status Code, following the [error handling conventions in openEO](#section/API-Principles/Error-Handling). Defaults to `400`.", + "default": 400 + } + } + } + }, + "process_parameters": { + "type": "array", + "description": "A list of parameters.\n\nThe order in the array corresponds to the parameter order to\nbe used in clients that don't support named parameters.\n\n**Note:** Specifying an empty array is different from (if allowed)\n`null` or the property being absent.\nAn empty array means the process has no parameters.\n`null` / property absent means that the parameters are unknown as\nthe user has not specified them. There could still be parameters in the\nprocess graph, if one is specified.", + "items": { + "$ref": "#/components/schemas/process_parameter" + } + }, + "base_parameter": { + "type": "object", + "required": [ + "name", + "description" + ], + "properties": { + "name": { + "type": "string", + "description": "A unique name for the parameter. \n\nIt is RECOMMENDED to use [snake case](https://en.wikipedia.org/wiki/Snake_case) (e.g. `window_size` or `scale_factor`).", + "pattern": "^\\w+$" }, - "service": { - "title": "Secondary Web Service", - "description": "The metadata of a secondary web service that has been submitted by the authenticated user.", - "type": "object", - "required": [ - "id", - "enabled", - "type", - "url" - ], - "properties": { - "id": { - "$ref": "#/components/schemas/service_id" - }, - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL at which the secondary web service is accessible. Doesn't necessarily need to be located within the API.", - "example": "https://openeo.example/wms/wms-a3cca9" - }, - "type": { - "$ref": "#/components/schemas/service_type" - }, - "enabled": { - "$ref": "#/components/schemas/service_enabled" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "configuration": { - "$ref": "#/components/schemas/service_configuration" - }, - "attributes": { - "title": "Secondary Web Service Attributes", - "type": "object", - "description": "Additional attributes of the secondary web service, e.g. available layers for a WMS based on the bands in the underlying GeoTiff.", - "example": { - "layers": [ - "ndvi", - "evi" - ] - } - }, - "created": { - "$ref": "#/components/schemas/created" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan" - }, - "costs": { - "$ref": "#/components/schemas/money" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "usage": { - "description": "Metrics about the resource usage of the secondary web service.\n\nBack-ends are not expected to update the metrics in real-time.\nFor detailed usage metrics for individual processing steps, metrics\ncan be added to the logs (e.g. `GET /jobs/{job_id}/logs`) with the\nsame schema.", - "allOf": [ - { - "$ref": "#/components/schemas/usage" - } - ] - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - } - } + "description": { + "$ref": "#/components/schemas/process_description" }, - "service_type": { - "description": "Definition of the service type to access result data. All available service types can be retrieved via `GET /service_types`. Service types MUST be accepted in a *case insensitive* manner.", - "type": "string", - "example": "wms" + "optional": { + "type": "boolean", + "description": "Determines whether this parameter is optional to be specified even when no default is specified.\nClients SHOULD automatically set this parameter to `true`, if a default value is specified. Back-ends SHOULD NOT fail, if a default value is specified and this flag is missing.", + "default": false }, - "service_configuration": { - "type": "object", - "title": "Service Configuration", - "description": "Map of configuration settings, i.e. the setting names supported by the secondary web service combined with actual values. See `GET /service_types` for supported configuration settings. For example, this could specify the required version of the service, visualization details or any other service dependant configuration.", - "example": { - "version": "1.3.0" - } + "deprecated": { + "$ref": "#/components/schemas/deprecated" }, - "service_enabled": { - "type": "boolean", - "description": "Describes whether a secondary web service is responding to requests (true) or not (false). Disabled services don't produce any costs." + "experimental": { + "$ref": "#/components/schemas/experimental" }, - "service_id": { - "type": "string", - "description": "A per-backend unique identifier of the secondary web service, generated by the back-end during creation. MUST match the specified pattern.", - "pattern": "^[\\w\\-\\.~]+$", - "example": "wms-a3cca9" + "default": { + "description": "The default value for this parameter. Required parameters SHOULD NOT specify a default value. Optional parameters SHOULD always specify a default value." + } + } + }, + "parameter": { + "title": "Parameter", + "type": "object", + "required": [ + "schema" + ], + "properties": { + "schema": { + "$ref": "#/components/schemas/data_type_schema" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/base_parameter" + } + ] + }, + "process_parameter": { + "title": "Process Parameter", + "type": "object", + "required": [ + "schema" + ], + "properties": { + "schema": { + "$ref": "#/components/schemas/process_schema" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/base_parameter" + } + ] + }, + "batch_job": { + "title": "Batch Job", + "description": "The metadata of a batch jobs that has been submitted by the authenticated user.", + "type": "object", + "required": [ + "id", + "status", + "created" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/job_id" }, - "resource_parameter": { - "x-additionalPropertiesName": "Parameter Name", - "type": "object", - "title": "Resource Parameter", - "description": "Describes a parameter for various resources (e.g. file formats, service types).\n\nThe parameters are specified according to the [JSON Schema draft-07](http://json-schema.org/) specification.\nSee the chapter ['Schemas' in 'Defining Processes'](#section/Processes/Defining-Processes) for more information.\n\nThe following more complex JSON Schema keywords SHOULD NOT be used:\n`if`, `then`, `else`, `readOnly`, `writeOnly`, `dependencies`, `minProperties`, `maxProperties`, `patternProperties`.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved). This allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema is only a common subset of JSON Schema. Additional keywords MAY be used.", - "required": [ - "description" - ], - "properties": { - "description": { - "type": "string", - "description": "A brief description of the parameter according to [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.10.1)." - }, - "required": { - "type": "boolean", - "description": "Determines whether this parameter is mandatory.", - "default": false - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "default": { - "description": "The default value represents what would be assumed by the consumer of the input as the value of the parameter if none is provided. The value MUST conform to the defined type for the parameter defined at the same level. For example, if type is string, then default can be \"foo\" but cannot be 1. See [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.10.2)." - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/process_json_schema" - } - ] + "title": { + "$ref": "#/components/schemas/eo_title" }, - "error": { - "title": "General Error", - "description": "An error object declares additional information about a client-side or server-side error.\nSee also: * [Error Handling](#section/API-Principles/Error-Handling) in the API in general. * [Common Error Codes](errors.json)", - "type": "object", - "required": [ - "code", - "message" - ], - "properties": { - "id": { - "type": "string", - "description": "A back-end MAY add a unique identifier to the error response to be able to log and track errors with further non-disclosable details. A client could communicate this id to a back-end provider to get further information.", - "example": "550e8400-e29b-11d4-a716-446655440000" - }, - "code": { - "$ref": "#/components/schemas/log_code" - }, - "message": { - "type": "string", - "description": "A message explaining what the client may need to change or what difficulties the server is facing.", - "example": "Parameter 'sample' is missing." - }, - "links": { - "$ref": "#/components/schemas/log_links" - } - } + "description": { + "$ref": "#/components/schemas/eo_description" }, - "log_code": { - "type": "string", - "description": "The code is either one of the standardized error codes or a custom code, for example specified by a user in the `inspect` process.", - "example": "SampleError" + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" }, - "log_links": { - "description": "Links related to this log entry / error, e.g. to a resource that\nprovides further explanations.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "href": "https://openeo.example/docs/errors/SampleError", - "rel": "about" - } - ] + "status": { + "type": "string", + "enum": [ + "created", + "queued", + "running", + "canceled", + "finished", + "error" + ], + "description": "The current status of a batch job.\n\nThe following status changes can occur:\n* `POST /jobs`: The status is initialized as `created`.\n* `POST /jobs/{job_id}/results`: The status is set to `queued`, if\nprocessing doesn't start instantly.\n * Once the processing starts the status is set to `running`.\n * Once the data is available to download the status is set to `finished`.\n * Whenever an error occurs during processing, the status MUST be set to `error`.\n* `DELETE /jobs/{job_id}/results`: The status is set to `canceled` if\nthe status was `running` beforehand and partial or preliminary results\nare available to be downloaded. Otherwise the status is set to\n`created`. ", + "example": "running", + "default": "created" }, - "log_level": { - "description": "The severity level of the log entry.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\n\nThe level `error` usually corresponds with critical issues that usually terminate the data processing.", - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "example": "error" + "progress": { + "type": "number", + "description": "Indicates the process of a running batch job in percent.\nCan also be set for a job which stopped due to an error or was canceled by the user. In this case, the value indicates the progress at which the job stopped. The Property may not be available for the status codes `created` and `queued`.\nSubmitted and queued jobs only allow the value `0`, finished jobs only allow the value `100`.", + "minimum": 0, + "maximum": 100, + "example": 75.5 }, - "min_log_level_default": { - "description": "The minimum severity level for log entries that the back-end stores for the processing request.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the back-end will only store log entries with the level `warning` and `error`.\n\nThe default minimum log level is `info`. Users need to specifically set this property to `debug` to get *all* log entries.\nIt is RECOMMENDED that users set the level at least to \"warning\" in production workflows.", - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "default": "info", - "example": "warning" + "created": { + "$ref": "#/components/schemas/created" }, - "min_log_level_update": { - "description": "Updates the minimum severity level for log entries that the back-end stores for the processing requests.\n\nThe back-end doesn't need to update existing log entries.", - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "example": "warning" + "updated": { + "$ref": "#/components/schemas/updated" }, - "data_type_schema": { - "title": "Data Types", - "description": "Either a single data type or a list of data types.", - "oneOf": [ - { - "$ref": "#/components/schemas/process_json_schema" - }, - { - "title": "Multiple data types", - "description": "A list of data types this parameter supports, specified as JSON Schemas.", - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/process_json_schema" - } - } - ] + "plan": { + "$ref": "#/components/schemas/billing_plan" }, - "process_schema": { - "title": "Process Data types", - "description": "Either a single data type or a list of data types for process parameter or process return values.", - "oneOf": [ - { - "$ref": "#/components/schemas/process_json_schema" - }, - { - "title": "Multiple data types", - "description": "A list of data types supported, specified as JSON Schemas.", - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/process_json_schema" - } - } - ] + "costs": { + "$ref": "#/components/schemas/money" }, - "process_json_schema": { - "type": "object", - "title": "Single Data Type", - "description": "Specifies a data type supported by a parameter or return value.\n\nThe data types are specified according to the [JSON Schema draft-07](http://json-schema.org/) specification.\nSee the chapter ['Schemas' in 'Defining Processes'](#section/Processes/Defining-Processes) for more information.\n\nJSON Schemas SHOULD NOT contain `default`, `anyOf`, `oneOf`, `allOf` or `not` at the top-level of the schema.\nInstead specify each data type in a separate array element.\n\nThe following more complex JSON Schema keywords SHOULD NOT be used:\n`if`, `then`, `else`, `readOnly`, `writeOnly`, `dependencies`, `minProperties`, `maxProperties`, `patternProperties`.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved). This allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema is only a common subset of JSON Schema. Additional keywords MAY be used.", - "properties": { - "subtype": { - "type": "string", - "description": "The allowed sub data type for a value. See the chapter on [subtypes](#section/Processes/Defining-Processes) for more information." - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/json_schema" - } - ], - "oneOf": [ - { - "title": "Generic" - }, - { - "$ref": "#/components/schemas/process_graph_json_schema" - }, - { - "$ref": "#/components/schemas/datacube_json_schema" - } - ] + "budget": { + "$ref": "#/components/schemas/budget" }, - "process_graph_json_schema": { - "title": "Process Graph", - "type": "object", - "properties": { - "subtype": { - "type": "string", - "enum": [ - "process-graph" - ] - }, - "parameters": { - "type": "array", - "title": "Process Graph Parameters", - "description": "A list of parameters passed to the child process graph.\n\nThe order in the array corresponds to the parameter order to\nbe used in clients that don't support named parameters.", - "items": { - "$ref": "#/components/schemas/parameter" - } - }, - "returns": { - "type": "object", - "title": "Process Graph Return Value", - "description": "Description of the data that is returned by the child process graph.", - "required": [ - "schema" - ], - "properties": { - "description": { - "$ref": "#/components/schemas/process_description" - }, - "schema": { - "$ref": "#/components/schemas/data_type_schema" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/process_json_schema" - } - ] - } + "usage": { + "description": "Metrics about the resource usage of the batch job.\n\nBack-ends are not expected to update the metrics while processing data,\nso the metrics can only be available after the job has finished\nor has stopped due to an error.\nFor usage metrics during processing, metrics can better be added to the\nlogs (e.g. `GET /jobs/{job_id}/logs`) with the same schema.", + "allOf": [ + { + "$ref": "#/components/schemas/usage" } + ] }, - "datacube_json_schema": { - "title": "Datacube", - "properties": { - "subtype": { - "type": "string", - "enum": [ - "datacube" - ] - }, - "dimensions": { - "title": "Datacube constraints", - "description": "Allows to specify requirements the data cube has to fulfill.\nRight now, it only allows to specify the dimension types and \nadds for specific dimension types:\n* axes for `spatial` dimensions in raster datacubes\n* geometry types for `geometry` dimensions in vector datacubes", - "type": "array", - "items": { - "type": "object", - "required": [ - "type" - ], - "oneOf": [ - { - "title": "Spatial (raster)", - "properties": { - "type": { - "type": "string", - "enum": [ - "spatial" - ] - }, - "axis": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/dimension_axis_xyz" - } - } - } - }, - { - "title": "Spatial (vector)", - "properties": { - "type": { - "type": "string", - "enum": [ - "geometry" - ] - }, - "geometry_type": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/geometry_type" - } - } - } - }, - { - "title": "Other", - "properties": { - "type": { - "type": "string", - "enum": [ - "bands", - "temporal", - "other" - ] - } - } - } - ] - } - } - } + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" }, - "json_schema": { - "type": "object", - "title": "JSON Schema", - "description": "A JSON Schema compliant to [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html) or later.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved).\nThis allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema in the OpenAPI document is only a common subset of JSON Schema.\nAdditional keywords from the JSON Schema specification MAY be used.", - "properties": { - "$schema": { - "description": "The JSON Schema version. If not given in the context of openEO,\ndefaults to `draft-07`.\n\nYou may need to add the default value for `$schema` property explicitly to the JSON Schema\nobject before passing it to a JSON Schema validator.", - "type": "string", - "format": "uri", - "default": "http://json-schema.org/draft-07/schema#" - }, - "$id": { - "description": "ID of your JSON Schema.", - "type": "string", - "format": "uri" - }, - "type": { - "description": "The allowed basic data type(s) for a value.\n\nIf this property is not present, all data types are allowed.", - "oneOf": [ - { - "$ref": "#/components/schemas/json_schema_type" - }, - { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/json_schema_type" - } - } - ] - }, - "pattern": { - "type": "string", - "format": "regex", - "description": "The regular expression a string value must match against." - }, - "enum": { - "type": "array", - "items": {}, - "description": "An exclusive list of allowed values." - }, - "minimum": { - "type": "number", - "description": "The minimum value (inclusive) allowed for a numerical value." - }, - "maximum": { - "type": "number", - "description": "The maximum value (inclusive) allowed for a numerical value." - }, - "minItems": { - "type": "number", - "minimum": 0, - "default": 0, - "description": "The minimum number of items required in an array." - }, - "maxItems": { - "type": "number", - "minimum": 0, - "description": "The maximum number of items required in an array." - }, - "items": { - "description": "Specifies schemas for the items in an array.", - "anyOf": [ - { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/json_schema" - } - }, - { - "$ref": "#/components/schemas/json_schema" - } - ] - } + "links": { + "type": "array", + "description": "Links related to this batch job, e.g. a links to \ninvoices, log files or results.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `monitor`: If logs are available, a link to the [logs endpoint](#tag/Batch-Jobs/operation/debug-job).\n2. `result`: If batch job results are available, a link to the [results endpoint](#tag/Batch-Jobs/operation/list-results).\n\nThe relation types `monitor` and `result` may occur for various batch job states:\n\n1. `created`: When the batch job was executed before and has been reset to `created` after an\n [update](#tag/Batch-Jobs/operation/update-job) there could still be results and logs available\n until they get discarded by [queueing the batch job again](#tag/Batch-Jobs/operation/start-job).\n2. `finished`: The full log and results are expected to be available.\n3. `error` / `canceled`: Partial results and logs may be available.\n\nFor more relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "rel": "result", + "type": "application/json", + "title": "Batch Job Results", + "href": "https://openeo.example/api/v1/jobs/123/logs" }, - "additionalProperties": { - "description": "You can add any other property supported by the JSON Schema version that is given through the property `$schema`, so either [draft-07](https://json-schema.org/draft-07/json-schema-validation.html) or any later version." + { + "rel": "result", + "type": "application/json", + "title": "Batch Job Logs", + "href": "https://openeo.example/api/v1/jobs/123/logs" } + ] + } + } + }, + "job_id": { + "type": "string", + "description": "Per-backend unique identifier of the batch job, generated by the back-end during creation. MUST match the specified pattern.", + "pattern": "^[\\w\\-\\.~]+$", + "example": "a3cca2b2aa1e3b5b" + }, + "created": { + "type": "string", + "format": "date-time", + "description": "Date and time of creation, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2017-01-01T09:32:12Z" + }, + "updated": { + "type": "string", + "format": "date-time", + "description": "Date and time of the last status change, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2017-01-01T09:36:18Z" + }, + "description": { + "type": "string", + "format": "commonmark", + "description": "Detailed description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation." + }, + "object_title": { + "type": "string", + "description": "A human-readable short title to be displayed to users **in addition** to the names specified in the keys. This property is only for better user experience so that users can understand the names better. Example titles could be `GeoTiff` for the key `GTiff` (for file formats) or `OGC Web Map Service` for the key `WMS` (for service types). The title MUST NOT be used in communication (e.g. in process graphs), although clients MAY translate the titles into the corresponding names." + }, + "eo_title": { + "description": "A short description to easily distinguish entities.", + "type": "string", + "nullable": true, + "example": "NDVI based on Sentinel 2" + }, + "eo_description": { + "type": "string", + "format": "commonmark", + "description": "Detailed multi-line description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", + "nullable": true, + "example": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2" + }, + "process_description": { + "type": "string", + "format": "commonmark", + "description": "Detailed description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. In addition to the CommonMark syntax, clients can convert process IDs that are formatted as in the following example into links instead of code blocks: ``` ``process_id()`` ```" + }, + "service": { + "title": "Secondary Web Service", + "description": "The metadata of a secondary web service that has been submitted by the authenticated user.", + "type": "object", + "required": [ + "id", + "enabled", + "type", + "url" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/service_id" }, - "json_schema_type": { - "type": "string", - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] + "title": { + "$ref": "#/components/schemas/eo_title" }, - "file": { - "title": "Workspace File", - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string", - "description": "Path of the file, relative to the root directory of the user's server-side workspace.\nMUST NOT start with a slash `/` and MUST NOT be url-encoded.\n\nThe Windows-style path name component separator `\\` is not supported,\nalways use `/` instead.\n\nNote: The pattern only specifies a minimal subset of invalid characters.\nThe back-ends MAY enforce additional restrictions depending on their OS/environment.", - "example": "folder/file.txt", - "pattern": "^[^/\r\n\\:'\"][^\r\n\\:'\"]*$" - }, - "size": { - "type": "integer", - "description": "File size in bytes.", - "example": 1024 - }, - "modified": { - "type": "string", - "format": "date-time", - "description": "Date and time the file has lastly been modified, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2018-01-03T10:55:29Z" - } - } + "description": { + "$ref": "#/components/schemas/eo_description" }, - "geometry_type": { - "title": "Geometry type", - "type": "string", - "enum": [ - "Point", - "MultiPoint", - "LineString", - "MultiLineString", - "Polygon", - "MultiPolygon", - "GeometryCollection" - ] + "url": { + "type": "string", + "format": "uri", + "description": "URL at which the secondary web service is accessible. Doesn't necessarily need to be located within the API.", + "example": "https://openeo.example/wms/wms-a3cca9" }, - "GeoJsonPoint3D": { - "type": "array", - "description": "Point in 3D space", - "minItems": 2, - "maxItems": 3, - "items": { - "type": "number" - } + "type": { + "$ref": "#/components/schemas/service_type" }, - "GeoJsonPoint": { - "type": "object", - "title": "GeoJSON Point", - "required": [ - "type", - "coordinates" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "Point" - ] - }, - "coordinates": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } + "enabled": { + "$ref": "#/components/schemas/service_enabled" }, - "GeoJsonFeatureCollection": { - "type": "object", - "required": [ - "type", - "features" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "FeatureCollection" - ] - }, - "features": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonFeature" - } - } - } + "process": { + "$ref": "#/components/schemas/process_graph_with_metadata" }, - "GeoJsonFeature": { - "type": "object", - "required": [ - "type", - "geometry", - "properties" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "Feature" - ] - }, - "geometry": { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - "properties": { - "type": "object", - "nullable": true - } - } + "configuration": { + "$ref": "#/components/schemas/service_configuration" }, - "GeoJson": { - "title": "GeoJSON", - "oneOf": [ - { - "$ref": "#/components/schemas/GeoJsonFeatureCollection" - }, - { - "$ref": "#/components/schemas/GeoJsonFeature" - }, - { - "$ref": "#/components/schemas/GeoJsonGeometry" - } + "attributes": { + "title": "Secondary Web Service Attributes", + "type": "object", + "description": "Additional attributes of the secondary web service, e.g. available layers for a WMS based on the bands in the underlying GeoTiff.", + "example": { + "layers": [ + "ndvi", + "evi" ] + } }, - "GeoJsonGeometry": { - "title": "GeoJSON Geometry", - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "$ref": "#/components/schemas/geometry_type" - } - }, - "discriminator": { - "propertyName": "type", - "mapping": { - "Point": "#/components/schemas/GeoJsonPoint", - "LineString": "#/components/schemas/GeoJsonLineString", - "Polygon": "#/components/schemas/GeoJsonPolygon", - "MultiPoint": "#/components/schemas/GeoJsonMultiPoint", - "MultiLineString": "#/components/schemas/GeoJsonMultiLineString", - "MultiPolygon": "#/components/schemas/GeoJsonMultiPolygon", - "GeometryCollection": "#/components/schemas/GeoJsonGeometryCollection" - } + "created": { + "$ref": "#/components/schemas/created" + }, + "plan": { + "$ref": "#/components/schemas/billing_plan" + }, + "costs": { + "$ref": "#/components/schemas/money" + }, + "budget": { + "$ref": "#/components/schemas/budget" + }, + "usage": { + "description": "Metrics about the resource usage of the secondary web service.\n\nBack-ends are not expected to update the metrics in real-time.\nFor detailed usage metrics for individual processing steps, metrics\ncan be added to the logs (e.g. `GET /jobs/{job_id}/logs`) with the\nsame schema.", + "allOf": [ + { + "$ref": "#/components/schemas/usage" } + ] }, - "GeoJsonLineString": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON LineString", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - ] + "log_level": { + "$ref": "#/components/schemas/min_log_level_default" + } + } + }, + "service_type": { + "description": "Definition of the service type to access result data. All available service types can be retrieved via `GET /service_types`. Service types MUST be accepted in a *case insensitive* manner.", + "type": "string", + "example": "wms" + }, + "service_configuration": { + "type": "object", + "title": "Service Configuration", + "description": "Map of configuration settings, i.e. the setting names supported by the secondary web service combined with actual values. See `GET /service_types` for supported configuration settings. For example, this could specify the required version of the service, visualization details or any other service dependant configuration.", + "example": { + "version": "1.3.0" + } + }, + "service_enabled": { + "type": "boolean", + "description": "Describes whether a secondary web service is responding to requests (true) or not (false). Disabled services don't produce any costs." + }, + "service_id": { + "type": "string", + "description": "A per-backend unique identifier of the secondary web service, generated by the back-end during creation. MUST match the specified pattern.", + "pattern": "^[\\w\\-\\.~]+$", + "example": "wms-a3cca9" + }, + "resource_parameter": { + "x-additionalPropertiesName": "Parameter Name", + "type": "object", + "title": "Resource Parameter", + "description": "Describes a parameter for various resources (e.g. file formats, service types).\n\nThe parameters are specified according to the [JSON Schema draft-07](http://json-schema.org/) specification.\nSee the chapter ['Schemas' in 'Defining Processes'](#section/Processes/Defining-Processes) for more information.\n\nThe following more complex JSON Schema keywords SHOULD NOT be used:\n`if`, `then`, `else`, `readOnly`, `writeOnly`, `dependencies`, `minProperties`, `maxProperties`, `patternProperties`.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved). This allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema is only a common subset of JSON Schema. Additional keywords MAY be used.", + "required": [ + "description" + ], + "properties": { + "description": { + "type": "string", + "description": "A brief description of the parameter according to [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.10.1)." }, - "GeoJsonPolygon": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON Polygon", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - } - ] + "required": { + "type": "boolean", + "description": "Determines whether this parameter is mandatory.", + "default": false }, - "GeoJsonMultiPoint": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON MultiPoint", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - ] + "experimental": { + "$ref": "#/components/schemas/experimental" }, - "GeoJsonMultiLineString": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON MultiLineString", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - } - ] + "default": { + "description": "The default value represents what would be assumed by the consumer of the input as the value of the parameter if none is provided. The value MUST conform to the defined type for the parameter defined at the same level. For example, if type is string, then default can be \"foo\" but cannot be 1. See [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.10.2)." + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/process_json_schema" + } + ] + }, + "error": { + "title": "General Error", + "description": "An error object declares additional information about a client-side or server-side error.\nSee also: * [Error Handling](#section/API-Principles/Error-Handling) in the API in general. * [Common Error Codes](errors.json)", + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "id": { + "type": "string", + "description": "A back-end MAY add a unique identifier to the error response to be able to log and track errors with further non-disclosable details. A client could communicate this id to a back-end provider to get further information.", + "example": "550e8400-e29b-11d4-a716-446655440000" }, - "GeoJsonMultiPolygon": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON MultiPolygon", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - } - } - ] + "code": { + "$ref": "#/components/schemas/log_code" }, - "GeoJsonGeometryCollection": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON GeometryCollection", - "required": [ - "geometries" - ], - "properties": { - "geometries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonGeometry" - } - } - } - } - ] + "message": { + "type": "string", + "description": "A message explaining what the client may need to change or what difficulties the server is facing.", + "example": "Parameter 'sample' is missing." }, - "log_entry": { - "title": "Log Entry", - "description": "An log message that communicates information about the processed data.", - "type": "object", - "required": [ - "id", - "level", - "message" - ], - "properties": { - "id": { - "type": "string", - "description": "An unique identifier for the log message, could simply be an incrementing number.", - "example": "1" - }, - "code": { - "$ref": "#/components/schemas/log_code" - }, - "level": { - "$ref": "#/components/schemas/log_level" - }, - "message": { - "type": "string", - "description": "A concise message explaining the log entry.\nMessages do *not* explicitly support [CommonMark 0.29](http://commonmark.org/) syntax as other descriptive fields in the openEO API do, but the messages MAY contain line breaks or indentation.\nIt is NOT RECOMMENDED to add stacktraces to the `message`.", - "example": "Can't load the UDF file from the URL `https://openeo.example/invalid/file.txt`. Server responded with error 404." - }, - "time": { - "type": "string", - "format": "date-time", - "title": "Date and Time", - "description": "The date and time the event happened, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." - }, - "data": { - "description": "Data of any type. It is the back-ends task to decide how to best\npresent passed data to a user.\n\nFor example, a datacube passed to the `inspect` SHOULD return the\nmetadata similar to the collection metadata, including `cube:dimensions`.\nThere are implementation guidelines available for the `inspect` process." - }, - "path": { - "description": "Describes where the log entry originates from.\n\nThe first element of the array is the process that has triggered the log entry, the second element is the parent of the process that has triggered the log entry, etc. This pattern is followed until the root of the process graph.", - "type": "array", - "items": { - "type": "object", - "required": [ - "node_id" - ], - "properties": { - "node_id": { - "type": "string", - "description": "The id of the node the log entry originates from.", - "example": "runudf1" - }, - "process_id": { - "$ref": "#/components/schemas/process_id" - }, - "namespace": { - "$ref": "#/components/schemas/process_namespace" - }, - "parameter": { - "type": "string", - "description": "If applicable, the name of the parameter the log entry corresponds to.", - "pattern": "^\\w+$", - "nullable": true, - "example": "udf" - } - } - } - }, - "usage": { - "$ref": "#/components/schemas/usage" - }, - "links": { - "$ref": "#/components/schemas/log_links" - } + "links": { + "$ref": "#/components/schemas/log_links" + } + } + }, + "log_code": { + "type": "string", + "description": "The code is either one of the standardized error codes or a custom code, for example specified by a user in the `inspect` process.", + "example": "SampleError" + }, + "log_links": { + "description": "Links related to this log entry / error, e.g. to a resource that\nprovides further explanations.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", + "type": "array", + "items": { + "$ref": "#/components/schemas/link" + }, + "example": [ + { + "href": "https://openeo.example/docs/errors/SampleError", + "rel": "about" + } + ] + }, + "log_level": { + "description": "The severity level of the log entry.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\n\nThe level `error` usually corresponds with critical issues that usually terminate the data processing.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "example": "error" + }, + "min_log_level_default": { + "description": "The minimum severity level for log entries that the back-end stores for the processing request.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the back-end will only store log entries with the level `warning` and `error`.\n\nThe default minimum log level is `info`. Users need to specifically set this property to `debug` to get *all* log entries.\nIt is RECOMMENDED that users set the level at least to \"warning\" in production workflows.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "default": "info", + "example": "warning" + }, + "min_log_level_update": { + "description": "Updates the minimum severity level for log entries that the back-end stores for the processing requests.\n\nThe back-end doesn't need to update existing log entries.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "example": "warning" + }, + "data_type_schema": { + "title": "Data Types", + "description": "Either a single data type or a list of data types.", + "oneOf": [ + { + "$ref": "#/components/schemas/process_json_schema" + }, + { + "title": "Multiple data types", + "description": "A list of data types this parameter supports, specified as JSON Schemas.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/process_json_schema" + } + } + ] + }, + "process_schema": { + "title": "Process Data types", + "description": "Either a single data type or a list of data types for process parameter or process return values.", + "oneOf": [ + { + "$ref": "#/components/schemas/process_json_schema" + }, + { + "title": "Multiple data types", + "description": "A list of data types supported, specified as JSON Schemas.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/process_json_schema" + } + } + ] + }, + "process_json_schema": { + "type": "object", + "title": "Single Data Type", + "description": "Specifies a data type supported by a parameter or return value.\n\nThe data types are specified according to the [JSON Schema draft-07](http://json-schema.org/) specification.\nSee the chapter ['Schemas' in 'Defining Processes'](#section/Processes/Defining-Processes) for more information.\n\nJSON Schemas SHOULD NOT contain `default`, `anyOf`, `oneOf`, `allOf` or `not` at the top-level of the schema.\nInstead specify each data type in a separate array element.\n\nThe following more complex JSON Schema keywords SHOULD NOT be used:\n`if`, `then`, `else`, `readOnly`, `writeOnly`, `dependencies`, `minProperties`, `maxProperties`, `patternProperties`.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved). This allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema is only a common subset of JSON Schema. Additional keywords MAY be used.", + "properties": { + "subtype": { + "type": "string", + "description": "The allowed sub data type for a value. See the chapter on [subtypes](#section/Processes/Defining-Processes) for more information." + }, + "deprecated": { + "$ref": "#/components/schemas/deprecated" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/json_schema" + } + ], + "oneOf": [ + { + "title": "Generic" + }, + { + "$ref": "#/components/schemas/process_graph_json_schema" + }, + { + "$ref": "#/components/schemas/datacube_json_schema" + } + ] + }, + "process_graph_json_schema": { + "title": "Process Graph", + "type": "object", + "properties": { + "subtype": { + "type": "string", + "enum": [ + "process-graph" + ] + }, + "parameters": { + "type": "array", + "title": "Process Graph Parameters", + "description": "A list of parameters passed to the child process graph.\n\nThe order in the array corresponds to the parameter order to\nbe used in clients that don't support named parameters.", + "items": { + "$ref": "#/components/schemas/parameter" + } + }, + "returns": { + "type": "object", + "title": "Process Graph Return Value", + "description": "Description of the data that is returned by the child process graph.", + "required": [ + "schema" + ], + "properties": { + "description": { + "$ref": "#/components/schemas/process_description" + }, + "schema": { + "$ref": "#/components/schemas/data_type_schema" } + }, + "allOf": [ + { + "$ref": "#/components/schemas/process_json_schema" + } + ] + } + } + }, + "datacube_json_schema": { + "title": "Datacube", + "properties": { + "subtype": { + "type": "string", + "enum": [ + "datacube" + ] }, - "usage": { - "title": "Resource usage metrics", + "dimensions": { + "title": "Datacube constraints", + "description": "Allows to specify requirements the data cube has to fulfill.\nRight now, it only allows to specify the dimension types and \nadds for specific dimension types:\n* axes for `spatial` dimensions in raster datacubes\n* geometry types for `geometry` dimensions in vector datacubes", + "type": "array", + "items": { "type": "object", - "properties": { - "cpu": { - "description": "Specifies the CPU usage, usually in a unit such as `cpu-seconds`.", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "memory": { - "description": "Specifies the memory usage, usually in a unit such as `mb-seconds` or `gb-hours`.", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "duration": { - "description": "Specifies the wall time, usually in a unit such as `seconds`, `minutes` or `hours`.", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "network": { - "description": "Specifies the network transfer usage (incoming and outgoing), usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } + "required": [ + "type" + ], + "oneOf": [ + { + "title": "Spatial (raster)", + "properties": { + "type": { + "type": "string", + "enum": [ + "spatial" ] - }, - "disk": { - "description": "Specifies the amount of input (read) and output (write) operations on the storage such as disks, usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } + }, + "axis": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/dimension_axis_xyz" + } + } + } + }, + { + "title": "Spatial (vector)", + "properties": { + "type": { + "type": "string", + "enum": [ + "geometry" ] - }, - "storage": { - "description": "Specifies the usage of storage space, usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } + }, + "geometry_type": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/geometry_type" + } + } + } + }, + { + "title": "Other", + "properties": { + "type": { + "type": "string", + "enum": [ + "bands", + "temporal", + "other" ] + } } + } + ] + } + } + } + }, + "json_schema": { + "type": "object", + "title": "JSON Schema", + "description": "A JSON Schema compliant to [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html) or later.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved).\nThis allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema in the OpenAPI document is only a common subset of JSON Schema.\nAdditional keywords from the JSON Schema specification MAY be used.", + "properties": { + "$schema": { + "description": "The JSON Schema version. If not given in the context of openEO,\ndefaults to `draft-07`.\n\nYou may need to add the default value for `$schema` property explicitly to the JSON Schema\nobject before passing it to a JSON Schema validator.", + "type": "string", + "format": "uri", + "default": "http://json-schema.org/draft-07/schema#" + }, + "$id": { + "description": "ID of your JSON Schema.", + "type": "string", + "format": "uri" + }, + "type": { + "description": "The allowed basic data type(s) for a value.\n\nIf this property is not present, all data types are allowed.", + "oneOf": [ + { + "$ref": "#/components/schemas/json_schema_type" }, - "additionalProperties": { - "description": "Additional metrics.", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] + { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/json_schema_type" + } + } + ] + }, + "pattern": { + "type": "string", + "format": "regex", + "description": "The regular expression a string value must match against." + }, + "enum": { + "type": "array", + "items": {}, + "description": "An exclusive list of allowed values." + }, + "minimum": { + "type": "number", + "description": "The minimum value (inclusive) allowed for a numerical value." + }, + "maximum": { + "type": "number", + "description": "The maximum value (inclusive) allowed for a numerical value." + }, + "minItems": { + "type": "number", + "minimum": 0, + "default": 0, + "description": "The minimum number of items required in an array." + }, + "maxItems": { + "type": "number", + "minimum": 0, + "description": "The maximum number of items required in an array." + }, + "items": { + "description": "Specifies schemas for the items in an array.", + "anyOf": [ + { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/json_schema" + } }, - "example": { - "cpu": { - "value": 40668, - "unit": "cpu-seconds" - }, - "duration": { - "value": 2611, - "unit": "seconds" - }, - "memory": { - "value": 108138811, - "unit": "mb-seconds" - }, - "network": { - "value": 0, - "unit": "kb" - }, - "storage": { - "value": 55, - "unit": "mb" - } + { + "$ref": "#/components/schemas/json_schema" } + ] + } + }, + "additionalProperties": { + "description": "You can add any other property supported by the JSON Schema version that is given through the property `$schema`, so either [draft-07](https://json-schema.org/draft-07/json-schema-validation.html) or any later version." + } + }, + "json_schema_type": { + "type": "string", + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "file": { + "title": "Workspace File", + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string", + "description": "Path of the file, relative to the root directory of the user's server-side workspace.\nMUST NOT start with a slash `/` and MUST NOT be url-encoded.\n\nThe Windows-style path name component separator `\\` is not supported,\nalways use `/` instead.\n\nNote: The pattern only specifies a minimal subset of invalid characters.\nThe back-ends MAY enforce additional restrictions depending on their OS/environment.", + "example": "folder/file.txt", + "pattern": "^[^/\r\n\\:'\"][^\r\n\\:'\"]*$" }, - "usage_metric": { - "type": "object", - "required": [ - "value", - "unit" - ], - "properties": { - "value": { - "type": "number", - "minimum": 0 - }, - "unit": { - "type": "string" - } + "size": { + "type": "integer", + "description": "File size in bytes.", + "example": 1024 + }, + "modified": { + "type": "string", + "format": "date-time", + "description": "Date and time the file has lastly been modified, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", + "example": "2018-01-03T10:55:29Z" + } + } + }, + "geometry_type": { + "title": "Geometry type", + "type": "string", + "enum": [ + "Point", + "MultiPoint", + "LineString", + "MultiLineString", + "Polygon", + "MultiPolygon", + "GeometryCollection" + ] + }, + "GeoJsonPoint3D": { + "type": "array", + "description": "Point in 3D space", + "minItems": 2, + "maxItems": 3, + "items": { + "type": "number" + } + }, + "GeoJsonPoint": { + "type": "object", + "title": "GeoJSON Point", + "required": [ + "type", + "coordinates" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "Point" + ] + }, + "coordinates": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } + } + }, + "GeoJsonFeatureCollection": { + "type": "object", + "required": [ + "type", + "features" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "FeatureCollection" + ] + }, + "features": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonFeature" + } + } + } + }, + "GeoJsonFeature": { + "type": "object", + "required": [ + "type", + "geometry", + "properties" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "Feature" + ] + }, + "geometry": { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + "properties": { + "type": "object", + "nullable": true + } + } + }, + "GeoJson": { + "title": "GeoJSON", + "oneOf": [ + { + "$ref": "#/components/schemas/GeoJsonFeatureCollection" + }, + { + "$ref": "#/components/schemas/GeoJsonFeature" + }, + { + "$ref": "#/components/schemas/GeoJsonGeometry" + } + ] + }, + "GeoJsonGeometry": { + "title": "GeoJSON Geometry", + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "$ref": "#/components/schemas/geometry_type" + } + }, + "discriminator": { + "propertyName": "type", + "mapping": { + "Point": "#/components/schemas/GeoJsonPoint", + "LineString": "#/components/schemas/GeoJsonLineString", + "Polygon": "#/components/schemas/GeoJsonPolygon", + "MultiPoint": "#/components/schemas/GeoJsonMultiPoint", + "MultiLineString": "#/components/schemas/GeoJsonMultiLineString", + "MultiPolygon": "#/components/schemas/GeoJsonMultiPolygon", + "GeometryCollection": "#/components/schemas/GeoJsonGeometryCollection" + } + } + }, + "GeoJsonLineString": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + { + "type": "object", + "title": "GeoJSON LineString", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } } + } } + ] }, - "responses": { - "logs": { - "description": "Lists the requested log entries.", - "content": { - "application/json": { - "schema": { - "title": "Log Entries", - "type": "object", - "required": [ - "logs", - "links" - ], - "properties": { - "level": { - "description": "The minimum severity level for log entries that the back-end returns.\nThis property MUST reflect the effective lowest `level` that may appear in the document,\nwhich is (if implemented) the highest level of:\n1. the `log_level` specified by the user for the processing request.\n2. the `level` specified by the user for the log request.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the logs will only contain entries with the level `warning` and `error`.", - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "default": "debug" - }, - "logs": { - "description": "A chronological list of logs.", - "type": "array", - "items": { - "$ref": "#/components/schemas/log_entry" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - } + "GeoJsonPolygon": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" + }, + { + "type": "object", + "title": "GeoJSON Polygon", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" } + } } + } + } + ] + }, + "GeoJsonMultiPoint": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" }, - "client_error": { - "description": "The request can't be fulfilled due to an error on client-side, i.e. the\nrequest is invalid. The client SHOULD NOT repeat the request without\nmodifications.\n\nThe response body SHOULD contain a JSON error object.\nMUST be any HTTP status code specified in [RFC\n7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6). This request\nusually does not respond with HTTP status codes 401 and 403 due to\nmissing authorization. HTTP status code 404 SHOULD be used if the value\nof a path parameter is invalid.\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/error" - } - } + { + "type": "object", + "title": "GeoJSON MultiPoint", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } } + } + } + ] + }, + "GeoJsonMultiLineString": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" }, - "client_error_auth": { - "description": "The request can't be fulfilled due to an error on client-side, i.e. the\nrequest is invalid. The client SHOULD NOT repeat the request without\nmodifications.\n\nThe response body SHOULD contain a JSON error object.\nMUST be any HTTP status code specified in [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6).\nThis request MUST respond with HTTP status codes 401 if authorization is required or\n403 if the authorization failed or access is forbidden in general to the\nauthenticated user. HTTP status code 404 SHOULD be used if the value of\na path parameter is invalid.\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/error" - } + { + "type": "object", + "title": "GeoJSON MultiLineString", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" } + } } + } + } + ] + }, + "GeoJsonMultiPolygon": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" }, - "server_error": { - "description": "The request can't be fulfilled due to an error at the back-end. The\nerror is never the client\u2019s fault and therefore it is reasonable for the\nclient to retry the exact same request that triggered this response.\n\nThe response body SHOULD contain a JSON error object. MUST be any HTTP\nstatus code specified in [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6).\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/error" - } + { + "type": "object", + "title": "GeoJSON MultiPolygon", + "required": [ + "coordinates" + ], + "properties": { + "coordinates": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonPoint3D" + } } + } } + } } + ] }, - "parameters": { - "pagination_limit": { - "name": "limit", - "description": "This parameter enables pagination for the endpoint and specifies the maximum number of\nelements that arrays in the top-level object (e.g. collections, processes, batch jobs,\nsecondary services, log entries, etc.) are allowed to contain.\nThe `links` array MUST NOT be paginated like the resources,\nbut instead contain links related to the paginated resources\nor the pagination itself (e.g. a link to the next page).\nIf the parameter is not provided or empty, all elements are returned.\n\nPagination is OPTIONAL: back-ends or clients may not support it.\nTherefore it MUST be implemented in a way that clients not supporting\npagination get all resources regardless. Back-ends not supporting\npagination MUST return all resources.\n\nIf the response is paginated, the `links` array MUST be used to communicate the\nlinks for browsing the pagination with predefined `rel` types. See the `links` array schema\nfor supported `rel` types.\nBack-end implementations can, unless specified otherwise, use all kind of pagination techniques,\ndepending on what is supported best by their infrastructure: page-based, offset-based, token-based\nor something else. The clients SHOULD use whatever is specified\nin the links with the corresponding `rel` types.", - "in": "query", - "allowEmptyValue": true, - "example": 10, - "schema": { - "type": "integer", - "minimum": 1 - } + "GeoJsonGeometryCollection": { + "allOf": [ + { + "$ref": "#/components/schemas/GeoJsonGeometry" }, - "log_offset": { - "name": "offset", - "description": "The last identifier (property `id` of a log entry) the client has received. If provided, the back-ends only sends the entries that occurred after the specified identifier. If not provided or empty, start with the first entry.", - "in": "query", - "allowEmptyValue": true, - "example": "log1234", - "schema": { - "type": "string" + { + "type": "object", + "title": "GeoJSON GeometryCollection", + "required": [ + "geometries" + ], + "properties": { + "geometries": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GeoJsonGeometry" + } } + } + } + ] + }, + "log_entry": { + "title": "Log Entry", + "description": "An log message that communicates information about the processed data.", + "type": "object", + "required": [ + "id", + "level", + "message" + ], + "properties": { + "id": { + "type": "string", + "description": "An unique identifier for the log message, could simply be an incrementing number.", + "example": "1" }, - "log_level": { - "name": "level", - "description": "The minimum severity level for log entries that the back-end returns.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the back-end will only return log entries with the level `warning` and `error`.\n\nThe default minimum log level is `debug`, which returns all log levels.", - "in": "query", - "allowEmptyValue": true, - "example": "error", - "schema": { + "code": { + "$ref": "#/components/schemas/log_code" + }, + "level": { + "$ref": "#/components/schemas/log_level" + }, + "message": { + "type": "string", + "description": "A concise message explaining the log entry.\nMessages do *not* explicitly support [CommonMark 0.29](http://commonmark.org/) syntax as other descriptive fields in the openEO API do, but the messages MAY contain line breaks or indentation.\nIt is NOT RECOMMENDED to add stacktraces to the `message`.", + "example": "Can't load the UDF file from the URL `https://openeo.example/invalid/file.txt`. Server responded with error 404." + }, + "time": { + "type": "string", + "format": "date-time", + "title": "Date and Time", + "description": "The date and time the event happened, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." + }, + "data": { + "description": "Data of any type. It is the back-ends task to decide how to best\npresent passed data to a user.\n\nFor example, a datacube passed to the `inspect` SHOULD return the\nmetadata similar to the collection metadata, including `cube:dimensions`.\nThere are implementation guidelines available for the `inspect` process." + }, + "path": { + "description": "Describes where the log entry originates from.\n\nThe first element of the array is the process that has triggered the log entry, the second element is the parent of the process that has triggered the log entry, etc. This pattern is followed until the root of the process graph.", + "type": "array", + "items": { + "type": "object", + "required": [ + "node_id" + ], + "properties": { + "node_id": { "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "default": "info" + "description": "The id of the node the log entry originates from.", + "example": "runudf1" + }, + "process_id": { + "$ref": "#/components/schemas/process_id" + }, + "namespace": { + "$ref": "#/components/schemas/process_namespace" + }, + "parameter": { + "type": "string", + "description": "If applicable, the name of the parameter the log entry corresponds to.", + "pattern": "^\\w+$", + "nullable": true, + "example": "udf" + } } + } }, - "service_id": { - "name": "service_id", - "in": "path", - "description": "Identifier of the secondary web service.", - "required": true, - "schema": { - "$ref": "#/components/schemas/service_id" + "usage": { + "$ref": "#/components/schemas/usage" + }, + "links": { + "$ref": "#/components/schemas/log_links" + } + } + }, + "usage": { + "title": "Resource usage metrics", + "type": "object", + "properties": { + "cpu": { + "description": "Specifies the CPU usage, usually in a unit such as `cpu-seconds`.", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" } + ] }, - "job_id": { - "name": "job_id", - "in": "path", - "description": "Identifier of the batch job.", - "required": true, - "schema": { - "$ref": "#/components/schemas/job_id" + "memory": { + "description": "Specifies the memory usage, usually in a unit such as `mb-seconds` or `gb-hours`.", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" } + ] }, - "collection_id": { - "name": "collection_id", - "in": "path", - "description": "Collection identifier", - "required": true, - "schema": { - "$ref": "#/components/schemas/collection_id" + "duration": { + "description": "Specifies the wall time, usually in a unit such as `seconds`, `minutes` or `hours`.", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "network": { + "description": "Specifies the network transfer usage (incoming and outgoing), usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "disk": { + "description": "Specifies the amount of input (read) and output (write) operations on the storage such as disks, usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "storage": { + "description": "Specifies the usage of storage space, usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" } + ] + } + }, + "additionalProperties": { + "description": "Additional metrics.", + "allOf": [ + { + "$ref": "#/components/schemas/usage_metric" + } + ] + }, + "example": { + "cpu": { + "value": 40668, + "unit": "cpu-seconds" + }, + "duration": { + "value": 2611, + "unit": "seconds" + }, + "memory": { + "value": 108138811, + "unit": "mb-seconds" + }, + "network": { + "value": 0, + "unit": "kb" + }, + "storage": { + "value": 55, + "unit": "mb" } + } }, - "examples": { - "evi_user_defined_process": { - "description": "A user-defined process that computes the EVI.", - "value": { - "id": "evi", - "summary": "Enhanced Vegetation Index", - "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", - "parameters": [ - { - "name": "red", - "description": "Value from the red band.", - "schema": { - "type": "number" - } - }, - { - "name": "blue", - "description": "Value from the blue band.", - "schema": { - "type": "number" - } - }, - { - "name": "nir", - "description": "Value from the near infrared band.", - "schema": { - "type": "number" - } - } + "usage_metric": { + "type": "object", + "required": [ + "value", + "unit" + ], + "properties": { + "value": { + "type": "number", + "minimum": 0 + }, + "unit": { + "type": "string" + } + } + } + }, + "responses": { + "logs": { + "description": "Lists the requested log entries.", + "content": { + "application/json": { + "schema": { + "title": "Log Entries", + "type": "object", + "required": [ + "logs", + "links" + ], + "properties": { + "level": { + "description": "The minimum severity level for log entries that the back-end returns.\nThis property MUST reflect the effective lowest `level` that may appear in the document,\nwhich is (if implemented) the highest level of:\n1. the `log_level` specified by the user for the processing request.\n2. the `level` specified by the user for the log request.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the logs will only contain entries with the level `warning` and `error`.", + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" ], - "returns": { - "description": "Computed EVI.", - "schema": { - "type": "number" - } - }, - "process_graph": { - "sub": { - "process_id": "subtract", - "arguments": { - "x": { - "from_parameter": "nir" - }, - "y": { - "from_parameter": "red" - } - } - }, - "p1": { - "process_id": "multiply", - "arguments": { - "x": 6, - "y": { - "from_parameter": "red" - } - } - }, - "p2": { - "process_id": "multiply", - "arguments": { - "x": -7.5, - "y": { - "from_parameter": "blue" - } - } - }, - "sum": { - "process_id": "sum", - "arguments": { - "data": [ - 1, - { - "from_parameter": "nir" - }, - { - "from_node": "p1" - }, - { - "from_node": "p2" - } - ] - } - }, - "div": { - "process_id": "divide", - "arguments": { - "x": { - "from_node": "sub" - }, - "y": { - "from_node": "sum" - } - } - }, - "p3": { - "process_id": "multiply", - "arguments": { - "x": 2.5, - "y": { - "from_node": "div" - } - }, - "result": true - } + "default": "debug" + }, + "logs": { + "description": "A chronological list of logs.", + "type": "array", + "items": { + "$ref": "#/components/schemas/log_entry" } + }, + "links": { + "$ref": "#/components/schemas/links_pagination" + } } + } + } + } + }, + "client_error": { + "description": "The request can't be fulfilled due to an error on client-side, i.e. the\nrequest is invalid. The client SHOULD NOT repeat the request without\nmodifications.\n\nThe response body SHOULD contain a JSON error object.\nMUST be any HTTP status code specified in [RFC\n7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6). This request\nusually does not respond with HTTP status codes 401 and 403 due to\nmissing authorization. HTTP status code 404 SHOULD be used if the value\nof a path parameter is invalid.\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "client_error_auth": { + "description": "The request can't be fulfilled due to an error on client-side, i.e. the\nrequest is invalid. The client SHOULD NOT repeat the request without\nmodifications.\n\nThe response body SHOULD contain a JSON error object.\nMUST be any HTTP status code specified in [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6).\nThis request MUST respond with HTTP status codes 401 if authorization is required or\n403 if the authorization failed or access is forbidden in general to the\nauthenticated user. HTTP status code 404 SHOULD be used if the value of\na path parameter is invalid.\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } } + } }, - "securitySchemes": { - "Bearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "The Bearer Token MUST consist of the authentication method, a provider ID (if available) and the token itself. All separated by a forward slash `/`. Examples (replace `TOKEN` with the actual access token): (1) Basic authentication (no provider ID available): `basic//TOKEN` (2) OpenID Connect (provider ID is `ms`): `oidc/ms/TOKEN`. For OpenID Connect, the provider ID corresponds to the value specified for `id` for each provider in `GET /credentials/oidc`." + "server_error": { + "description": "The request can't be fulfilled due to an error at the back-end. The\nerror is never the client’s fault and therefore it is reasonable for the\nclient to retry the exact same request that triggered this response.\n\nThe response body SHOULD contain a JSON error object. MUST be any HTTP\nstatus code specified in [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6).\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + } + }, + "parameters": { + "pagination_limit": { + "name": "limit", + "description": "This parameter enables pagination for the endpoint and specifies the maximum number of\nelements that arrays in the top-level object (e.g. collections, processes, batch jobs,\nsecondary services, log entries, etc.) are allowed to contain.\nThe `links` array MUST NOT be paginated like the resources,\nbut instead contain links related to the paginated resources\nor the pagination itself (e.g. a link to the next page).\nIf the parameter is not provided or empty, all elements are returned.\n\nPagination is OPTIONAL: back-ends or clients may not support it.\nTherefore it MUST be implemented in a way that clients not supporting\npagination get all resources regardless. Back-ends not supporting\npagination MUST return all resources.\n\nIf the response is paginated, the `links` array MUST be used to communicate the\nlinks for browsing the pagination with predefined `rel` types. See the `links` array schema\nfor supported `rel` types.\nBack-end implementations can, unless specified otherwise, use all kind of pagination techniques,\ndepending on what is supported best by their infrastructure: page-based, offset-based, token-based\nor something else. The clients SHOULD use whatever is specified\nin the links with the corresponding `rel` types.", + "in": "query", + "allowEmptyValue": true, + "example": 10, + "schema": { + "type": "integer", + "minimum": 1 + } + }, + "log_offset": { + "name": "offset", + "description": "The last identifier (property `id` of a log entry) the client has received. If provided, the back-ends only sends the entries that occurred after the specified identifier. If not provided or empty, start with the first entry.", + "in": "query", + "allowEmptyValue": true, + "example": "log1234", + "schema": { + "type": "string" + } + }, + "log_level": { + "name": "level", + "description": "The minimum severity level for log entries that the back-end returns.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the back-end will only return log entries with the level `warning` and `error`.\n\nThe default minimum log level is `debug`, which returns all log levels.", + "in": "query", + "allowEmptyValue": true, + "example": "error", + "schema": { + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ], + "default": "info" + } + }, + "service_id": { + "name": "service_id", + "in": "path", + "description": "Identifier of the secondary web service.", + "required": true, + "schema": { + "$ref": "#/components/schemas/service_id" + } + }, + "job_id": { + "name": "job_id", + "in": "path", + "description": "Identifier of the batch job.", + "required": true, + "schema": { + "$ref": "#/components/schemas/job_id" + } + }, + "collection_id": { + "name": "collection_id", + "in": "path", + "description": "Collection identifier", + "required": true, + "schema": { + "$ref": "#/components/schemas/collection_id" + } + } + }, + "examples": { + "evi_user_defined_process": { + "description": "A user-defined process that computes the EVI.", + "value": { + "id": "evi", + "summary": "Enhanced Vegetation Index", + "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", + "parameters": [ + { + "name": "red", + "description": "Value from the red band.", + "schema": { + "type": "number" + } + }, + { + "name": "blue", + "description": "Value from the blue band.", + "schema": { + "type": "number" + } + }, + { + "name": "nir", + "description": "Value from the near infrared band.", + "schema": { + "type": "number" + } + } + ], + "returns": { + "description": "Computed EVI.", + "schema": { + "type": "number" + } }, - "Basic": { - "type": "http", - "scheme": "basic" + "process_graph": { + "sub": { + "process_id": "subtract", + "arguments": { + "x": { + "from_parameter": "nir" + }, + "y": { + "from_parameter": "red" + } + } + }, + "p1": { + "process_id": "multiply", + "arguments": { + "x": 6, + "y": { + "from_parameter": "red" + } + } + }, + "p2": { + "process_id": "multiply", + "arguments": { + "x": -7.5, + "y": { + "from_parameter": "blue" + } + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_parameter": "nir" + }, + { + "from_node": "p1" + }, + { + "from_node": "p2" + } + ] + } + }, + "div": { + "process_id": "divide", + "arguments": { + "x": { + "from_node": "sub" + }, + "y": { + "from_node": "sum" + } + } + }, + "p3": { + "process_id": "multiply", + "arguments": { + "x": 2.5, + "y": { + "from_node": "div" + } + }, + "result": true + } } + } + } + }, + "securitySchemes": { + "Bearer": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "The Bearer Token MUST consist of the authentication method, a provider ID (if available) and the token itself. All separated by a forward slash `/`. Examples (replace `TOKEN` with the actual access token): (1) Basic authentication (no provider ID available): `basic//TOKEN` (2) OpenID Connect (provider ID is `ms`): `oidc/ms/TOKEN`. For OpenID Connect, the provider ID corresponds to the value specified for `id` for each provider in `GET /credentials/oidc`." + }, + "Basic": { + "type": "http", + "scheme": "basic" } + } } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/payload_examples/empty_payload/empty_payload.json b/src/openeo_test_suite/tests/general/payload_examples/empty_payload/empty_payload.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/src/openeo_test_suite/tests/general/payload_examples/empty_payload/empty_payload.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/payload_examples/mock_processes/mock_processes_0.json b/src/openeo_test_suite/tests/general/payload_examples/mock_processes/mock_processes_0.json new file mode 100644 index 0000000..e5d41d0 --- /dev/null +++ b/src/openeo_test_suite/tests/general/payload_examples/mock_processes/mock_processes_0.json @@ -0,0 +1,133 @@ +{ + "processes": [ + { + "id": "apply", + "summary": "Apply a process to each pixel", + "description": "Applies a *unary* process to each pixel value in the data cube (i.e. a local operation). A unary process takes a single value and returns a single value, for example ``abs()`` or ``linear_scale_range()``.", + "categories": [ + "cubes" + ], + "parameters": [ + { + "name": "data", + "description": "A data cube.", + "schema": { + "type": "object", + "subtype": "datacube" + } + }, + { + "name": "process", + "description": "A unary process to be applied on each value, may consist of multiple sub-processes.", + "schema": { + "type": "object", + "subtype": "process-graph", + "parameters": [ + { + "name": "x", + "description": "The value to process.", + "schema": { + "description": "Any data type." + } + } + ] + } + } + ], + "returns": { + "description": "A data cube with the newly computed values. The resolution, cardinality and the number of dimensions are the same as for the original data cube.", + "schema": { + "type": "object", + "subtype": "datacube" + } + } + }, + { + "id": "multiply", + "summary": "Multiplication of two numbers", + "description": "Multiplies the two numbers `x` and `y` (*x * y*) and returns the computed product.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", + "categories": [ + "math" + ], + "parameters": [ + { + "name": "x", + "description": "The multiplier.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + { + "name": "y", + "description": "The multiplicand.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The computed product of the two numbers.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + "exceptions": { + "MultiplicandMissing": { + "message": "Multiplication requires at least two numbers." + } + }, + "examples": [ + { + "arguments": { + "x": 5, + "y": 2.5 + }, + "returns": 12.5 + }, + { + "arguments": { + "x": -2, + "y": -4 + }, + "returns": 8 + }, + { + "arguments": { + "x": 1, + "y": null + }, + "returns": null + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/Product.html", + "title": "Product explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/8766229", + "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" + } + ] + } + ], + "links": [ + { + "rel": "alternate", + "href": "https://openeo.example/processes", + "type": "text/html", + "title": "HTML version of the processes" + } + ] + } \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/payload_examples/patch_jobs/patch_jobs_1.json b/src/openeo_test_suite/tests/general/payload_examples/patch_jobs/patch_jobs_1.json new file mode 100644 index 0000000..49883f0 --- /dev/null +++ b/src/openeo_test_suite/tests/general/payload_examples/patch_jobs/patch_jobs_1.json @@ -0,0 +1,342 @@ +{ + "title": "NDVI based on Sentinel 2", + "description": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2", + "process": { + "id": "ndvi", + "summary": "string", + "description": "string", + "parameters": [ + { + "schema": { + "parameters": [ + { + "schema": { + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + }, + "name": "string", + "description": "string", + "optional": false, + "deprecated": false, + "experimental": false, + "default": null + } + ], + "returns": { + "description": "string", + "schema": { + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + }, + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + }, + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + }, + "name": "string", + "description": "string", + "optional": false, + "deprecated": false, + "experimental": false, + "default": null + } + ], + "returns": { + "description": "string", + "schema": { + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + } + }, + "categories": [ + "string" + ], + "deprecated": false, + "experimental": false, + "exceptions": { + "Error Code1": { + "description": "string", + "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", + "http": 400 + }, + "Error Code2": { + "description": "string", + "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", + "http": 400 + } + }, + "examples": [ + { + "title": "string", + "description": "string", + "arguments": { + "property1": { + "from_parameter": null, + "from_node": null, + "process_graph": null + }, + "property2": { + "from_parameter": null, + "from_node": null, + "process_graph": null + } + }, + "returns": null + } + ], + "links": [ + { + "rel": "related", + "href": "https://example.openeo.org", + "type": "text/html", + "title": "openEO" + } + ], + "process_graph": { + "dc": { + "process_id": "load_collection", + "arguments": { + "id": "Sentinel-2", + "spatial_extent": { + "west": 16.1, + "east": 16.6, + "north": 48.6, + "south": 47.2 + }, + "temporal_extent": [ + "2018-01-01", + "2018-02-01" + ] + } + }, + "bands": { + "process_id": "filter_bands", + "description": "Filter and order the bands. The order is important for the following reduce operation.", + "arguments": { + "data": { + "from_node": "dc" + }, + "bands": [ + "B08", + "B04", + "B02" + ] + } + }, + "evi": { + "process_id": "reduce", + "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", + "arguments": { + "data": { + "from_node": "bands" + }, + "dimension": "bands", + "reducer": { + "process_graph": { + "nir": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 0 + } + }, + "red": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 1 + } + }, + "blue": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 2 + } + }, + "sub": { + "process_id": "subtract", + "arguments": { + "data": [ + { + "from_node": "nir" + }, + { + "from_node": "red" + } + ] + } + }, + "p1": { + "process_id": "product", + "arguments": { + "data": [ + 6, + { + "from_node": "red" + } + ] + } + }, + "p2": { + "process_id": "product", + "arguments": { + "data": [ + -7.5, + { + "from_node": "blue" + } + ] + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_node": "nir" + }, + { + "from_node": "p1" + }, + { + "from_node": "p2" + } + ] + } + }, + "div": { + "process_id": "divide", + "arguments": { + "data": [ + { + "from_node": "sub" + }, + { + "from_node": "sum" + } + ] + } + }, + "p3": { + "process_id": "product", + "arguments": { + "data": [ + 2.5, + { + "from_node": "div" + } + ] + }, + "result": true + } + } + } + } + }, + "mintime": { + "process_id": "reduce", + "description": "Compute a minimum time composite by reducing the temporal dimension", + "arguments": { + "data": { + "from_node": "evi" + }, + "dimension": "temporal", + "reducer": { + "process_graph": { + "min": { + "process_id": "min", + "arguments": { + "data": { + "from_parameter": "data" + } + }, + "result": true + } + } + } + } + }, + "save": { + "process_id": "save_result", + "arguments": { + "data": { + "from_node": "mintime" + }, + "format": "GTiff" + }, + "result": true + } + } + }, + "plan": "free", + "budget": 100 + } \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/payload_examples/post_jobs/post_jobs_1.json b/src/openeo_test_suite/tests/general/payload_examples/post_jobs/post_jobs_1.json new file mode 100644 index 0000000..63caf63 --- /dev/null +++ b/src/openeo_test_suite/tests/general/payload_examples/post_jobs/post_jobs_1.json @@ -0,0 +1,41 @@ +{ + "title": "Custom Test Process", + "description": "Loads and Saves austrian ground motion data", + "process": { + "process_graph": { + "load1": { + "process_id": "load_collection", + "arguments": { + "bands": [ + "B01" + ], + "properties": {}, + "id": "CGLS_SSM_1KM", + "spatial_extent": { + "west": 16.186110851391813, + "east": 16.576456845030226, + "south": 48.08764096726651, + "north": 48.29291292355549 + }, + "temporal_extent": [ + "2020-01-01T00:00:00Z", + "2020-12-13T00:00:00Z" + ] + } + }, + "save2": { + "process_id": "save_result", + "arguments": { + "data": { + "from_node": "load1" + }, + "format": "NETCDF" + }, + "result": true + } + }, + "parameters": [] + }, + "plan": "free", + "budget": 100 + } \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/payload_examples/post_result/post_result_1.json b/src/openeo_test_suite/tests/general/payload_examples/post_result/post_result_1.json new file mode 100644 index 0000000..e3f20ae --- /dev/null +++ b/src/openeo_test_suite/tests/general/payload_examples/post_result/post_result_1.json @@ -0,0 +1,340 @@ +{ + "process": { + "id": "ndvi", + "summary": "string", + "description": "string", + "parameters": [ + { + "schema": { + "parameters": [ + { + "schema": { + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + }, + "name": "string", + "description": "string", + "optional": false, + "deprecated": false, + "experimental": false, + "default": null + } + ], + "returns": { + "description": "string", + "schema": { + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + }, + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + }, + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + }, + "name": "string", + "description": "string", + "optional": false, + "deprecated": false, + "experimental": false, + "default": null + } + ], + "returns": { + "description": "string", + "schema": { + "type": "array", + "subtype": "string", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "deprecated": false + } + }, + "categories": [ + "string" + ], + "deprecated": false, + "experimental": false, + "exceptions": { + "Error Code1": { + "description": "string", + "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", + "http": 400 + }, + "Error Code2": { + "description": "string", + "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", + "http": 400 + } + }, + "examples": [ + { + "title": "string", + "description": "string", + "arguments": { + "property1": { + "from_parameter": null, + "from_node": null, + "process_graph": null + }, + "property2": { + "from_parameter": null, + "from_node": null, + "process_graph": null + } + }, + "returns": null + } + ], + "links": [ + { + "rel": "related", + "href": "https://example.openeo.org", + "type": "text/html", + "title": "openEO" + } + ], + "process_graph": { + "dc": { + "process_id": "load_collection", + "arguments": { + "id": "Sentinel-2", + "spatial_extent": { + "west": 16.1, + "east": 16.6, + "north": 48.6, + "south": 47.2 + }, + "temporal_extent": [ + "2018-01-01", + "2018-02-01" + ] + } + }, + "bands": { + "process_id": "filter_bands", + "description": "Filter and order the bands. The order is important for the following reduce operation.", + "arguments": { + "data": { + "from_node": "dc" + }, + "bands": [ + "B08", + "B04", + "B02" + ] + } + }, + "evi": { + "process_id": "reduce", + "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", + "arguments": { + "data": { + "from_node": "bands" + }, + "dimension": "bands", + "reducer": { + "process_graph": { + "nir": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 0 + } + }, + "red": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 1 + } + }, + "blue": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 2 + } + }, + "sub": { + "process_id": "subtract", + "arguments": { + "data": [ + { + "from_node": "nir" + }, + { + "from_node": "red" + } + ] + } + }, + "p1": { + "process_id": "product", + "arguments": { + "data": [ + 6, + { + "from_node": "red" + } + ] + } + }, + "p2": { + "process_id": "product", + "arguments": { + "data": [ + -7.5, + { + "from_node": "blue" + } + ] + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_node": "nir" + }, + { + "from_node": "p1" + }, + { + "from_node": "p2" + } + ] + } + }, + "div": { + "process_id": "divide", + "arguments": { + "data": [ + { + "from_node": "sub" + }, + { + "from_node": "sum" + } + ] + } + }, + "p3": { + "process_id": "product", + "arguments": { + "data": [ + 2.5, + { + "from_node": "div" + } + ] + }, + "result": true + } + } + } + } + }, + "mintime": { + "process_id": "reduce", + "description": "Compute a minimum time composite by reducing the temporal dimension", + "arguments": { + "data": { + "from_node": "evi" + }, + "dimension": "temporal", + "reducer": { + "process_graph": { + "min": { + "process_id": "min", + "arguments": { + "data": { + "from_parameter": "data" + } + }, + "result": true + } + } + } + } + }, + "save": { + "process_id": "save_result", + "arguments": { + "data": { + "from_node": "mintime" + }, + "format": "GTiff" + }, + "result": true + } + } + }, + "budget": 100, + "plan": "free" + } \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/payload_examples/post_validation/post_validation_1.json b/src/openeo_test_suite/tests/general/payload_examples/post_validation/post_validation_1.json new file mode 100644 index 0000000..fa29b57 --- /dev/null +++ b/src/openeo_test_suite/tests/general/payload_examples/post_validation/post_validation_1.json @@ -0,0 +1,103 @@ +{ + "id": "evi", + "summary": "Enhanced Vegetation Index", + "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", + "parameters": [ + { + "name": "red", + "description": "Value from the red band.", + "schema": { + "type": "number" + } + }, + { + "name": "blue", + "description": "Value from the blue band.", + "schema": { + "type": "number" + } + }, + { + "name": "nir", + "description": "Value from the near infrared band.", + "schema": { + "type": "number" + } + } + ], + "returns": { + "description": "Computed EVI.", + "schema": { + "type": "number" + } + }, + "process_graph": { + "sub": { + "process_id": "subtract", + "arguments": { + "x": { + "from_parameter": "nir" + }, + "y": { + "from_parameter": "red" + } + } + }, + "p1": { + "process_id": "multiply", + "arguments": { + "x": 6, + "y": { + "from_parameter": "red" + } + } + }, + "p2": { + "process_id": "multiply", + "arguments": { + "x": -7.5, + "y": { + "from_parameter": "blue" + } + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_parameter": "nir" + }, + { + "from_node": "p1" + }, + { + "from_node": "p2" + } + ] + } + }, + "div": { + "process_id": "divide", + "arguments": { + "x": { + "from_node": "sub" + }, + "y": { + "from_node": "sum" + } + } + }, + "p3": { + "process_id": "multiply", + "arguments": { + "x": 2.5, + "y": { + "from_node": "div" + } + }, + "result": true + } + } + } \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/payload_examples/put_process_graphs/put_process_graphs_1.json b/src/openeo_test_suite/tests/general/payload_examples/put_process_graphs/put_process_graphs_1.json new file mode 100644 index 0000000..9ded78e --- /dev/null +++ b/src/openeo_test_suite/tests/general/payload_examples/put_process_graphs/put_process_graphs_1.json @@ -0,0 +1,103 @@ +{ + "id": "evil", + "summary": "Enhanced Vegetation Index", + "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", + "parameters": [ + { + "name": "red", + "description": "Value from the red band.", + "schema": { + "type": "number" + } + }, + { + "name": "blue", + "description": "Value from the blue band.", + "schema": { + "type": "number" + } + }, + { + "name": "nir", + "description": "Value from the near infrared band.", + "schema": { + "type": "number" + } + } + ], + "returns": { + "description": "Computed EVI.", + "schema": { + "type": "number" + } + }, + "process_graph": { + "sub": { + "process_id": "subtract", + "arguments": { + "x": { + "from_parameter": "nir" + }, + "y": { + "from_parameter": "red" + } + } + }, + "p1": { + "process_id": "multiply", + "arguments": { + "x": 6, + "y": { + "from_parameter": "red" + } + } + }, + "p2": { + "process_id": "multiply", + "arguments": { + "x": -7.5, + "y": { + "from_parameter": "blue" + } + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_parameter": "nir" + }, + { + "from_node": "p1" + }, + { + "from_node": "p2" + } + ] + } + }, + "div": { + "process_id": "divide", + "arguments": { + "x": { + "from_node": "sub" + }, + "y": { + "from_node": "sum" + } + } + }, + "p3": { + "process_id": "multiply", + "arguments": { + "x": 2.5, + "y": { + "from_node": "div" + } + }, + "result": true + } + } +} \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/test_compliance.py b/src/openeo_test_suite/tests/general/test_compliance.py index 8351576..47f3e06 100644 --- a/src/openeo_test_suite/tests/general/test_compliance.py +++ b/src/openeo_test_suite/tests/general/test_compliance.py @@ -21,14 +21,16 @@ def domain(request): @pytest.fixture(scope="session") def spec(request): return conformance_util.adjust_spec_json( - conformance_util.get_spec_path_json(), conformance_util.get_base_url(request) + conformance_util.get_spec_path_json(), + conformance_util.get_base_url(request), + conformance_util.get_domain(request), ) @pytest.fixture(scope="session") -def bearer_token(): - bearer_token = conformance_util.get_access_token() - return f"Bearer oidc/egi/{bearer_token}" +def bearer_token(pytestconfig): + bearer_token = conformance_util.get_access_token(pytestconfig) + return f"Bearer {bearer_token}" # endregion @@ -57,7 +59,7 @@ def test_GET_backend_info(base_url: str, spec: Spec, bearer_token: str): assert fail_log == "" -def test_GET_well_known(domain: str): +def test_GET_well_known(domain: str, spec: Spec, bearer_token: str): """ tests all the generic GET endpoints that require neither setup nor cleanup @@ -65,11 +67,8 @@ def test_GET_well_known(domain: str): testing: test response by API for GET requests cleanup: Change server back potentially """ - spec = conformance_util.adjust_spec_well_known_json( - conformance_util.get_spec_path_json(), domain - ) - endpoint_path = ".well-known/openeo" + endpoint_path = "/.well-known/openeo" test_name = "Well known" # Run through all the generic GET endpoints and test their response to a proper request. @@ -238,8 +237,6 @@ def test_GET_me(base_url: str, spec: Spec, bearer_token: str): assert fail_log == "" - -def test_GET_collections_collection_id(base_url: str, spec: Spec, bearer_token: str): """ setup: collect list of collection ids testing: test response by API for GET requests of all the collection ids @@ -430,7 +427,7 @@ def test_DELETE_process_graphs_process_id(base_url: str, spec: Spec, bearer_toke spec=spec, bearer_token=bearer_token, method="DELETE", - expected_status_code=204, + expected_status_codes=204, ) # CLEANUP @@ -508,7 +505,7 @@ def test_POST_jobs(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=payload, method="POST", - expected_status_code=201, + expected_status_codes=201, return_response=True, ) @@ -602,7 +599,7 @@ def test_PATCH_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=payload, method="PATCH", - expected_status_code=204, + expected_status_codes=204, ) # CLEANUP @@ -643,7 +640,7 @@ def test_DELETE_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): spec=spec, bearer_token=bearer_token, method="DELETE", - expected_status_code=204, + expected_status_codes=204, ) # CLEANUP @@ -679,7 +676,7 @@ def test_POST_jobs_job_id_results(base_url: str, spec: Spec, bearer_token: str): spec=spec, bearer_token=bearer_token, method="POST", - expected_status_code=202, + expected_status_codes=202, ) # CLEANUP @@ -785,7 +782,7 @@ def test_DELETE_jobs_job_id_results(base_url: str, spec: Spec, bearer_token: str spec=spec, bearer_token=bearer_token, method="DELETE", - expected_status_code=204, + expected_status_codes=204, ) # CLEANUP @@ -912,7 +909,7 @@ def test_POST_result(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=payload, method="POST", - expected_status_code=201, + expected_status_codes=201, ) # CLEANUP @@ -989,7 +986,7 @@ def test_none_PUT_process_graphs_process_id( payload=None, bearer_token=bearer_token, method="PUT", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1021,7 +1018,7 @@ def test_negative_DELETE_process_graphs_process_id( spec=spec, bearer_token=bearer_token, method="DELETE", - expected_status_code=500, + expected_status_codes=range(400, 501), ) # CLEANUP @@ -1047,7 +1044,7 @@ def test_none_POST_jobs(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=None, method="POST", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1081,7 +1078,7 @@ def test_none_PATCH_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=None, method="PATCH", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1114,7 +1111,7 @@ def test_negative_DELETE_jobs_job_id(base_url: str, spec: Spec, bearer_token: st spec=spec, bearer_token=bearer_token, method="DELETE", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1143,7 +1140,7 @@ def test_negative_POST_jobs_job_id_results( spec=spec, bearer_token=bearer_token, method="POST", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1170,7 +1167,7 @@ def test_negative_GET_jobs_job_id_results(base_url: str, spec: Spec, bearer_toke spec=spec, bearer_token=bearer_token, method="GET", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1199,7 +1196,7 @@ def test_negative_DELETE_jobs_job_id_results( spec=spec, bearer_token=bearer_token, method="DELETE", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1228,7 +1225,7 @@ def test_negative_GET_jobs_job_id_logs(base_url: str, spec: Spec, bearer_token: spec=spec, bearer_token=bearer_token, method="GET", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1258,7 +1255,7 @@ def test_none_POST_result(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=None, method="POST", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1285,7 +1282,7 @@ def test_none_POST_validation(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=None, method="POST", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1328,7 +1325,7 @@ def test_empty_PUT_process_graphs_process_id( payload=payload, bearer_token=bearer_token, method="PUT", - expected_status_code=500, + expected_status_codes=range(400, 501), ) # CLEANUP @@ -1363,7 +1360,7 @@ def test_empty_POST_jobs(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=payload, method="POST", - expected_status_code=500, + expected_status_codes=range(400, 501), ) # CLEANUP @@ -1406,7 +1403,7 @@ def test_empty_PATCH_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=payload, method="PATCH", - expected_status_code=204, + expected_status_codes=204, ) # CLEANUP @@ -1451,7 +1448,7 @@ def test_empty_POST_result(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=payload, method="POST", - expected_status_code=422, + expected_status_codes=range(400, 500), ) # CLEANUP @@ -1487,7 +1484,7 @@ def test_empty_POST_validation(base_url: str, spec: Spec, bearer_token: str): bearer_token=bearer_token, payload=payload, method="POST", - expected_status_code=200, + expected_status_codes=200, ) # CLEANUP From 332b07e873d896628cde37ec9441c1198ef82ea0 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Mon, 5 Feb 2024 17:54:46 +0100 Subject: [PATCH 03/12] Remove WP3 changes from PR --- src/openeo_test_suite/lib/process_registry.py | 11 - .../metadata/test_process_metadata.py | 190 ------------------ 2 files changed, 201 deletions(-) delete mode 100644 src/openeo_test_suite/tests/processes/metadata/test_process_metadata.py diff --git a/src/openeo_test_suite/lib/process_registry.py b/src/openeo_test_suite/lib/process_registry.py index 66aaab1..eea2ca4 100644 --- a/src/openeo_test_suite/lib/process_registry.py +++ b/src/openeo_test_suite/lib/process_registry.py @@ -1,4 +1,3 @@ -import json import logging import os from dataclasses import dataclass @@ -17,7 +16,6 @@ class ProcessData: """Process data, including profile level and list of tests""" process_id: str - metadata: dict level: str tests: List[dict] # TODO: also make dataclass for each test? experimental: bool @@ -65,7 +63,6 @@ def _load(self) -> Iterator[ProcessData]: raise ValueError(f"Invalid process test root directory: {self._root}") _log.info(f"Loading process definitions from {self._root}") for path in self._root.glob("*.json5"): - metadata_path = path.parent.parent / f"{path.stem}.json" try: with path.open() as f: data = json5.load(f) @@ -73,16 +70,8 @@ def _load(self) -> Iterator[ProcessData]: raise ValueError( f"Process id mismatch between id {data['id']!r} and filename {path.name!r}" ) - # Metadata is stored in sibling json file - if metadata_path.exists(): - with metadata_path.open() as f: - metadata = json.load(f) - else: - metadata = {} - yield ProcessData( process_id=data["id"], - metadata=metadata, level=data.get("level"), tests=data.get("tests", []), experimental=data.get("experimental", False), diff --git a/src/openeo_test_suite/tests/processes/metadata/test_process_metadata.py b/src/openeo_test_suite/tests/processes/metadata/test_process_metadata.py deleted file mode 100644 index f8aab3c..0000000 --- a/src/openeo_test_suite/tests/processes/metadata/test_process_metadata.py +++ /dev/null @@ -1,190 +0,0 @@ -import json -import pytest -import requests -from openeo_test_suite.lib.process_selection import get_selected_processes -from openeo_test_suite.lib.backend_under_test import get_backend_url - - -@pytest.fixture(scope="module") -def api_processes(request): - endpoint_path = "processes" - base_url = get_backend_url(request.config) - if not base_url: - raise ValueError("No backend URL configured") - if base_url.endswith("/"): - base_url = base_url[:-1] - full_endpoint_url = f"{base_url}/{endpoint_path}" - response = json.loads(requests.get(full_endpoint_url).content) - return response["processes"] - - -_get_selected_processes = get_selected_processes.__wrapped__ - - -def get_examples(): - """Collect process examples/tests from examples root folder containing JSON5 files.""" - return [process for process in _get_selected_processes()] - - -@pytest.mark.parametrize( - "expected_process", - [process for process in get_examples() if process.metadata != {}], - ids=[process.process_id for process in get_examples() if process.metadata != {}], -) -def test_process_metadata_functional(api_processes, expected_process): - """ - Tests if the metadata of processes are correct, first tests if the process exists, - then tests if the parameters of processes are correct and finally tests if the return type of processes is correct. - - Any process that has no metadata is skipped. - - These are the functional parts of the process metadata, e.g. existence (has to be checked) the parameters and return type. - """ - # Tests if the process exists - assert expected_process.process_id in [ - process["id"] for process in api_processes - ], f"The process '{expected_process.process_id}' was not found on the backend" - - # Tests if the parameters of processes are correct - - expected_parameters = expected_process.metadata.get("parameters", []) - actual_parameters = [ - process - for process in api_processes - if process["id"] == expected_process.process_id - ][0]["parameters"] - for expected_parameter, actual_parameter in zip( - expected_parameters, actual_parameters - ): - # Tests if parameter names are equivalent - assert ( - expected_parameter["name"] == actual_parameter["name"] - ), f"The parameter named '{actual_parameter['name']}' of the process \ - '{expected_process.process_id}' should be named '{expected_parameter['name']}'" - # Tests if optionality of parameters is equivalent - assert expected_parameter.get("optional", False) == actual_parameter.get( - "optional", False - ), f"The parameter named '{actual_parameter['name']}' of the process \ - '{expected_process.process_id}' should have '{expected_parameter.get('optional', False)}' optionality" - # Tests if the type of parameters is equivalent - assert ( - expected_parameter["schema"] == actual_parameter["schema"] - ), f"The parameter named '{actual_parameter['name']}' of the process \ - '{expected_process.process_id}' should have the schema '{expected_parameter['schema']}' \ - but has the schema '{actual_parameter['schema']}'" - - # Tests if the return type of processes is correct - expected_return_type = expected_process.metadata.get("returns", {}) - - actual_return_type = [ - process - for process in api_processes - if process["id"] == expected_process.process_id - ][0]["returns"] - print() - assert ( - expected_return_type["schema"] == actual_return_type["schema"] - ), f"The return type of the process '{expected_process.process_id}' should be \ - '{expected_return_type['schema']}' but is actually '{actual_return_type['schema']}'" - - -@pytest.mark.parametrize( - "expected_process", - [process for process in get_examples() if process.metadata != {}], - ids=[process.process_id for process in get_examples() if process.metadata != {}], -) -def test_process_metadata_non_functional(api_processes, expected_process): - """ - Tests if the non-functional metadata of processes are correct (descriptions and categories), first tests if the process exists, - then tests if the categories of processes are correct. - """ - - assert expected_process.process_id in [ - process["id"] for process in api_processes - ], f"The process '{expected_process.process_id}' was not found on the backend" - - # Tests if the categories of processes is equivalent - assert ( - expected_process.metadata.get("categories", []) - == [ - process - for process in api_processes - if process["id"] == expected_process.process_id - ][0]["categories"] - ), f"The process '{expected_process.process_id}' has the wrong categories, \ - should be '{expected_process.metadata.get('categories', [])}'\ - but is actually '{[process for process in api_processes if process['id'] == expected_process.process_id][0]['categories']}'" - - # Tests if the description of processes is equivalent - assert ( - expected_process.metadata.get("description", "") - == [ - process - for process in api_processes - if process["id"] == expected_process.process_id - ][0]["description"] - ), f"The process '{expected_process.process_id}' has the wrong description, \ - should be '{expected_process.metadata.get('description', '')}'\ - but is actually '{[process for process in api_processes if process['id'] == expected_process.process_id][0]['description']}'" - - # Tests if the summary of processes is equivalent - assert ( - expected_process.metadata.get("summary", "") - == [ - process - for process in api_processes - if process["id"] == expected_process.process_id - ][0]["summary"] - ), f"The process '{expected_process.process_id}' has the wrong summary, \ - should be '{expected_process.metadata.get('summary', '')}'\ - but is actually '{[process for process in api_processes if process['id'] == expected_process.process_id][0]['summary']}'" - - # Tests if the description of parameters is equivalent - expected_parameters = expected_process.metadata.get("parameters", []) - actual_parameters = [ - process - for process in api_processes - if process["id"] == expected_process.process_id - ][0]["parameters"] - - for expected_parameter, actual_parameter in zip( - expected_parameters, actual_parameters - ): - assert expected_parameter.get("description", "") == actual_parameter.get( - "description", "" - ), f"The parameter named '{actual_parameter['name']}' of the process \ - '{expected_process.process_id}' should have the description '{expected_parameter.get('description', '')}' \ - but has the description '{actual_parameter.get('description', '')}'" - - # Tests if the description of returns is equivalent - expected_return_type = expected_process.metadata.get("returns", {}) - actual_return_type = [ - process - for process in api_processes - if process["id"] == expected_process.process_id - ][0]["returns"] - assert expected_return_type.get("description", "") == actual_return_type.get( - "description", "" - ), f"The return type of the process '{expected_process.process_id}' should have the description \ - '{expected_return_type.get('description', '')}' but has the description '{actual_return_type.get('description', '')}'" - - # Tests if the links of processes are equivalent - expected_links = expected_process.metadata.get("links", []) - actual_links = [ - process - for process in api_processes - if process["id"] == expected_process.process_id - ][0]["links"] - for expected_link, actual_link in zip(expected_links, actual_links): - assert expected_link.get("href", "") == actual_link.get( - "href", "" - ), f"The link of the process '{expected_process.process_id}' should be \ - '{expected_link.get('href', '')}' but is actually '{actual_link.get('href', '')}'" - assert expected_link.get("rel", "") == actual_link.get( - "rel", "" - ), f"The link of the process '{expected_process.process_id}' should be \ - '{expected_link.get('rel', '')}' but is actually '{actual_link.get('rel', '')}'" - assert expected_link.get("title", "") == actual_link.get( - "title", "" - ), f"The link of the process '{expected_process.process_id}' should be \ - '{expected_link.get('title', '')}' but is actually '{actual_link.get('title', '')}'" From 4e873793d072817da1dc24132c630c57ea0cc555 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Tue, 6 Feb 2024 13:54:31 +0100 Subject: [PATCH 04/12] git submodule, relocate compliance_util --- .gitmodules | 3 + pytest.ini | 2 + .../{tests/general => lib}/compliance_util.py | 24 +- .../tests/general/openapi.json | 6651 ----------------- .../tests/general/openeo-api | 1 + .../tests/general/test_compliance.py | 12 +- 6 files changed, 21 insertions(+), 6672 deletions(-) create mode 100644 pytest.ini rename src/openeo_test_suite/{tests/general => lib}/compliance_util.py (96%) delete mode 100644 src/openeo_test_suite/tests/general/openapi.json create mode 160000 src/openeo_test_suite/tests/general/openeo-api diff --git a/.gitmodules b/.gitmodules index 6ebd274..5d9e2ee 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,6 @@ path = assets/processes url = https://github.com/Open-EO/openeo-processes branch = add-tests +[submodule "src/openeo_test_suite/tests/general/openeo-api"] + path = src/openeo_test_suite/tests/general/openeo-api + url = git@github.com:Open-EO/openeo-api.git diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..bac5362 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = -v --tb=short --openeo-backend-url=openeo.vito.be \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/compliance_util.py b/src/openeo_test_suite/lib/compliance_util.py similarity index 96% rename from src/openeo_test_suite/tests/general/compliance_util.py rename to src/openeo_test_suite/lib/compliance_util.py index 46683ae..a4cf77b 100644 --- a/src/openeo_test_suite/tests/general/compliance_util.py +++ b/src/openeo_test_suite/lib/compliance_util.py @@ -281,11 +281,9 @@ def check_test_results(e: Exception): return fail_log -# THIS IS A WORKAROUND, -# this can be removed IF the cause of ServerNotFound Exception has been fixed -def adjust_server_in_json(path_to_json, endpoint): - with open(path_to_json, "r") as file: - data = json.load(file) +def adjust_server(path_to_file, endpoint): + with open(path_to_file, "r") as file: + data = yaml.safe_load(file) if "servers" in data and isinstance(data["servers"], list): for server in data["servers"]: @@ -294,13 +292,13 @@ def adjust_server_in_json(path_to_json, endpoint): return data -def adjust_spec_json(path_to_json: str, endpoint: str, domain: str): - data = adjust_server_in_json(path_to_json=path_to_json, endpoint=endpoint) - data = adjust_server_in_well_known_json(data=data, endpoint=domain) +def adjust_spec(path_to_file: str, endpoint: str, domain: str): + data = adjust_server(path_to_file=path_to_file, endpoint=endpoint) + data = adjust_server_in_well_known(data=data, endpoint=domain) return Spec.from_dict(data, validator=None) -def adjust_server_in_well_known_json(data, endpoint): +def adjust_server_in_well_known(data, endpoint): data["paths"]["/.well-known/openeo"]["get"]["servers"][0]["url"] = endpoint return data @@ -330,8 +328,10 @@ def get_examples_path(): ) -def get_spec_path_json(): - return os.path.join(os.getcwd(), "src/openeo_test_suite/tests/general/openapi.json") +def get_spec_path(): + return os.path.join( + os.getcwd(), "src/openeo_test_suite/tests/general/openeo-api/openapi.yaml" + ) def load_payloads_from_directory(directory_path: str) -> list[dict]: @@ -454,7 +454,7 @@ def post_start_jobs(base_url: str, bearer_token: str): bearer_token=bearer_token, job_ids=created_batch_job_ids, job_statuses=["running"], - timeout=60, + timeout=10, ) return created_batch_job_ids diff --git a/src/openeo_test_suite/tests/general/openapi.json b/src/openeo_test_suite/tests/general/openapi.json deleted file mode 100644 index 40275ed..0000000 --- a/src/openeo_test_suite/tests/general/openapi.json +++ /dev/null @@ -1,6651 +0,0 @@ -{ - "openapi": "3.0.2", - "info": { - "title": "openEO API", - "version": "1.2.0", - "description": "The openEO API specification for interoperable cloud-based processing of large Earth observation datasets.\n\n**Conformance class:** `https://api.openeo.org/1.2.0`\n\n# API Principles\n\n## Language\n\nIn the specification the key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.html) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174.html).\n\n## Casing\n\nUnless otherwise stated the API works **case sensitive**.\n\nAll names SHOULD be written in snake case, i.e. words are separated with one underscore character (`_`) and no spaces, with all letters lower-cased. Example: `hello_world`. This applies particularly to endpoints and JSON property names. HTTP header fields are generally case-insensitive according to [RFC 7230](https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2) and in the specification we follow their respective casing conventions, e.g. `Content-Type` or `OpenEO-Costs`, for better readability and consistency.\n\n## HTTP / REST\n\nThis uses [HTTP REST](https://en.wikipedia.org/wiki/Representational_state_transfer) [Level 2](https://martinfowler.com/articles/richardsonMaturityModel.html#level2) for communication between client and back-end server.\n\nPublic APIs MUST be available via HTTPS only. \n\nEndpoints are made use meaningful HTTP verbs (e.g. GET, POST, PUT, PATCH, DELETE) whenever technically possible. If there is a need to transfer big chunks of data for a GET requests to the back-end, POST requests MAY be used as a replacement as they support to send data via request body. Unless otherwise stated, PATCH requests are only defined to work on direct (first-level) children of the full JSON object. Therefore, changing a property on a deeper level of the full JSON object always requires to send the whole JSON object defined by the first-level property.\n\nNaming of endpoints follow the REST principles. Therefore, endpoints are centered around resources. Resource identifiers MUST be named with a noun in plural form except for single actions that can not be modelled with the regular HTTP verbs. Single actions MUST be single endpoints with a single HTTP verb (POST is RECOMMENDED) and no other endpoints beneath it.\n\nThe openEO API makes use of [HTTP Content Negotiation](https://www.rfc-editor.org/rfc/rfc9110.html#name-content-negotiation),\nincluding, but not limited to, the request headers `Accept`, `Accept-Charset` and `Accept-Language`.\n\n### JSON\n\nThe API uses JSON for request and response bodies whenever feasible. Services use JSON as the default encoding. Other encodings can be requested using HTTP Content Negotiation ([`Accept` header](https://www.rfc-editor.org/rfc/rfc9110.html#name-accept)). Clients and servers MUST NOT rely on the order in which properties appear in JSON. To keep the response size small, lists of resources (e.g. the list of batch jobs) usually should not include nested JSON objects, if this information can be requested from the individual resource endpoints (e.g. the metadata for a single batch job).\n\n### Charset\n\nServices use [UTF-8](https://en.wikipedia.org/wiki/UTF-8) as the default charset if not negotiated otherwise with HTTP Content Negotiation ([`Accept-Charset` header](https://www.rfc-editor.org/rfc/rfc9110.html#name-accept-charset)).\n\n## Web Linking\n\nThe API is designed in a way that to most entities (e.g. collections and processes) a set of links can be added. These can be alternate representations, e.g. data discovery via OGC WCS or OGC CSW, references to a license, references to actual raw data for downloading, detailed information about pre-processing and more. Clients should allow users to follow the links.\n\nWhenever links are utilized in the API, the description explains which relation (`rel` property) types are commonly used.\nA [list of standardized link relations types is provided by IANA](https://www.iana.org/assignments/link-relations/link-relations.xhtml) and the API tries to align whenever feasible.\n\nSome very common relation types - usually not mentioned explicitly in the description of `links` fields - are:\n\n1. `self`: which allows link to the location that the resource can be (permanently) found online.This is particularly useful when the data is data is made available offline, so that the downstream user knows where the data has come from.\n\n2. `alternate`: An alternative representation of the resource, may it be another metadata standard the data is available in or simply a human-readable version in HTML or PDF.\n\n3. `about`: A resource that is related or further explains the resource, e.g. a user guide.\n\n4. `canonical`: This relation type usually points to a publicly accessible and more long-lived URL for a resource that otherwise often requires (Bearer) authentication with a short-lived token.\nThis way the the exposed resources can be used by non-openEO clients without additional authentication steps.\nFor example, a shared user-defined process or batch job results could be exposed via a canonical link.\nIf a URL should be publicly available to everyone, it can simply a user-specific URL, e.g. `https://openeo.example/processes/john_doe/ndvi`.\nFor resources that should only be accessible to a certain group of user, a signed URL could be given, e.g. `https://openeo.example/processes/81zjh1tc2pt52gbx/ndvi`.\n\nGenerally, it is RECOMMENDED to add descriptive titles (propertty `title`) and media type information (propertty `type`) for a better user experience.\n\n## Error Handling\n\nThe success of requests MUST be indicated using [HTTP status codes](https://www.rfc-editor.org/rfc/rfc7231.html#section-6) according to [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html).\n\nIf the API responds with a status code between 100 and 399 the back-end indicates that the request has been handled successfully.\n\nIn general an error is communicated with a status code between 400 and 599. Client errors are defined as a client passing invalid data to the service and the service *correctly* rejecting that data. Examples include invalid credentials, incorrect parameters, unknown versions, or similar. These are generally \"4xx\" HTTP error codes and are the result of a client passing incorrect or invalid data. Client errors do *not* contribute to overall API availability. \n\nServer errors are defined as the server failing to correctly return in response to a valid client request. These are generally \"5xx\" HTTP error codes. Server errors *do* contribute to the overall API availability. Calls that fail due to rate limiting or quota failures MUST NOT count as server errors. \n\n### JSON error object\n\nA JSON error object SHOULD be sent with all responses that have a status code between 400 and 599.\n\n``` json\n{\n \"id\": \"936DA01F-9ABD-4D9D-80C7-02AF85C822A8\",\n \"code\": \"SampleError\",\n \"message\": \"A sample error message.\",\n \"url\": \"https://openeo.example/docs/errors/SampleError\"\n}\n```\n\nSending `code` and `message` is REQUIRED. \n\n* A back-end MAY add a free-form `id` (unique identifier) to the error response to be able to log and track errors with further non-disclosable details.\n* The `code` is either one of the [standardized textual openEO error codes](errors.json) or a proprietary error code.\n* The `message` explains the reason the server is rejecting the request. For \"4xx\" error codes the message explains how the client needs to modify the request.\n\n By default the message MUST be sent in English language. Content Negotiation is used to localize the error messages: If an `Accept-Language` header is sent by the client and a translation is available, the message should be translated accordingly and the `Content-Language` header must be present in the response. See \"[How to localize your API](http://apiux.com/2013/04/25/how-to-localize-your-api/)\" for more information.\n* `url` is an OPTIONAL attribute and contains a link to a resource that is explaining the error and potential solutions in-depth.\n\n### Standardized status codes\n\nThe openEO API usually uses the following HTTP status codes for successful requests: \n\n- **200 OK**:\n Indicates a successful request **with** a response body being sent.\n- **201 Created**\n Indicates a successful request that successfully created a new resource. Sends a `Location` header to the newly created resource **without** a response body.\n- **202 Accepted**\n Indicates a successful request that successfully queued the creation of a new resource, but it has not been created yet. The response is sent **without** a response body.\n- **204 No Content**:\n Indicates a successful request **without** a response body being sent.\n\nThe openEO API has some commonly used HTTP status codes for failed requests: \n\n- **400 Bad Request**:\n The back-end responds with this error code whenever the error has its origin on client side and no other HTTP status code in the 400 range is suitable.\n\n- **401 Unauthorized**:\n The client did not provide any authentication details for a resource requiring authentication or the provided authentication details are not correct.\n\n- **403 Forbidden**:\n The client did provided correct authentication details, but the privileges/permissions of the provided credentials do not allow to request the resource.\n\n- **404 Not Found**:\n The resource specified by the path does not exist, i.e. one of the resources belonging to the specified identifiers are not available at the back-end.\n *Note:* Unsupported endpoints MAY also return HTTP status code 501.\n\n- **500 Internal Server Error**:\n The error has its origin on server side and no other status code in the 500 range is suitable.\n\n- **501 Not Implemented**:\n The requested endpoint is specified by the openEO API, but is not implemented (yet) by the back-end.\n *Note:* Unsupported endpoints MAY also return HTTP status code 404.\n\n\nIf a HTTP status code in the 400 range is returned, the client SHOULD NOT repeat the request without modifications. For HTTP status code in the 500 range, the client MAY repeat the same request later.\n\nAll HTTP status codes defined in RFC 7231 in the 400 and 500 ranges can be used as openEO error code in addition to the most used status codes mentioned here. Responding with openEO error codes 400 and 500 SHOULD be avoided in favor of any more specific standardized or proprietary openEO error code.\n\n## Temporal data\n\nDate, time, intervals and durations are formatted based on ISO 8601 or its profile [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) whenever there is an appropriate encoding available in the standard. All temporal data are specified based on the Gregorian calendar.\n\n# Authentication\n\nThe openEO API offers two forms of authentication by default:\n* OpenID Connect (recommended) at `GET /credentials/oidc`\n* Basic at `GET /credentials/basic`\n \nAfter authentication with any of the methods listed above, the tokens obtained during the authentication workflows can be sent to protected endpoints in subsequent requests.\n\nFurther authentication methods MAY be added by back-ends.\n\n\n\n**Note:** Although it is possible to request several public endpoints for capabilities and discovery that don't require authorization, it is RECOMMENDED that clients (re-)request the public endpoints that support Bearer authentication with the Bearer token once available to also retrieve any private data that is made available specifically for the authenticated user.\nThis may require that clients clear any cached data they retrieved from public endpoints before.\n\n# Cross-Origin Resource Sharing (CORS)\n\n> Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources [...] on a web page to be requested from another domain outside the domain from which the first resource was served. [...]\n> CORS defines a way in which a browser and server can interact to determine whether or not it is safe to allow the cross-origin request. It allows for more freedom and functionality than purely same-origin requests, but is more secure than simply allowing all cross-origin requests.\n\nSource: [https://en.wikipedia.org/wiki/Cross-origin_resource_sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)\n\nopenEO-based back-ends are usually hosted on a different domain / host than the client that is requesting data from the back-end. Therefore most requests to the back-end are blocked by all modern browsers. This leads to the problem that the JavaScript library and any browser-based application can't access back-ends. Therefore, all back-end providers SHOULD support CORS to enable browser-based applications to access back-ends. [CORS is a recommendation of the W3C organization](https://www.w3.org/TR/cors/). The following chapters will explain how back-end providers can implement CORS support.\n\n**Tip**: Most servers can send the required headers and the responses to the OPTIONS requests automatically for all endpoints. Otherwise you may also use a proxy server to add the headers and OPTIONS responses.\n\n## CORS headers\n\nThe following headers MUST be included with every response:\n\n| Name | Description | Example |\n| -------------------------------- | ------------------------------------------------------------ | ------- |\n| Access-Control-Allow-Origin | Allowed origin for the request, including protocol, host and port or `*` for all origins. It is RECOMMENDED to return the value `*` to allow requests from browser-based implementations such as the Web Editor. | `*` |\n| Access-Control-Expose-Headers | Some endpoints require to send additional HTTP response headers such as `OpenEO-Identifier` and `Location`. To make these headers available to browser-based clients, they MUST be white-listed with this CORS header. The following HTTP headers are white-listed by browsers and MUST NOT be included: `Cache-Control`, `Content-Language`, `Content-Length`, `Content-Type`, `Expires`, `Last-Modified` and `Pragma`. At least the following headers MUST be listed in this version of the openEO API: `Link`, `Location`, `OpenEO-Costs` and `OpenEO-Identifier`. | `Link, Location, OpenEO-Costs, OpenEO-Identifier` |\n\n\n\n### Example request and response\n\nRequest:\n\n```http\nPOST /api/v1/jobs HTTP/1.1\nHost: openeo.example\nOrigin: https://company.example:8080\nAuthorization: Bearer basic//ZXhhbXBsZTpleGFtcGxl\n```\n\nResponse:\n\n```http\nHTTP/1.1 201 Created\nAccess-Control-Allow-Origin: *\nAccess-Control-Expose-Headers: Location, OpenEO-Identifier, OpenEO-Costs, Link\nContent-Type: application/json\nLocation: https://openeo.example/api/v1/jobs/abc123\nOpenEO-Identifier: abc123\n```\n\n## OPTIONS method\n\nAll endpoints must respond to the `OPTIONS` HTTP method. This is a response for the preflight requests made by web browsers before sending the actual request (e.g. `POST /jobs`). It needs to respond with a status code of `204` and no response body.\n**In addition** to the HTTP headers shown in the table above, the following HTTP headers MUST be included with every response to an `OPTIONS` request:\n\n| Name | Description | Example |\n| -------------------------------- | ------------------------------------------------------------ | ------- |\n| Access-Control-Allow-Headers | Comma-separated list of HTTP headers allowed to be sent with the actual (non-preflight) request. MUST contain at least `Authorization` if any kind of authorization is implemented by the back-end. | `Authorization, Content-Type` |\n| Access-Control-Allow-Methods | Comma-separated list of HTTP methods allowed to be requested. Back-ends MUST list all implemented HTTP methods for the endpoint. | `OPTIONS, GET, POST, PATCH, PUT, DELETE` |\n| Content-Type | SHOULD return the content type delivered by the request that the permission is requested for. | `application/json` |\n\n### Example request and response\n\nRequest:\n\n```http\nOPTIONS /api/v1/jobs HTTP/1.1\nHost: openeo.example\nOrigin: https://company.example:8080\nAccess-Control-Request-Method: POST \nAccess-Control-Request-Headers: Authorization, Content-Type\n```\n\nNote that the `Access-Control-Request-*` headers are automatically attached to the requests by the browsers.\n\nResponse:\n\n```http\nHTTP/1.1 204 No Content\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: OPTIONS, GET, POST, PATCH, PUT, DELETE\nAccess-Control-Allow-Headers: Authorization, Content-Type\nAccess-Control-Expose-Headers: Location, OpenEO-Identifier, OpenEO-Costs, Link\nContent-Type: application/json\n```\n\n# Processes\n\nA **process** is an operation that performs a specific task on a set of parameters and returns a result. An example is computing a statistical operation, such as mean or median, on selected EO data. A process is similar to a function or method in programming languages. In openEO, processes are used to build a chain of processes ([process graph](#section/Processes/Process-Graphs)), which can be applied to EO data to derive your own findings from the data.\n\nA **predefined process** is a process provided by the *back-end*. There is a set of predefined processes by openEO to improve interoperability between back-ends.\nBack-ends SHOULD follow these specifications whenever possible. Not all processes need to be implemented by all back-ends. See the **[process reference](https://processes.openeo.org)** for predefined processes.\n\nA **user-defined process** is a process defined by the *user*. It can directly be part of another process graph or be stored as custom process on a back-end. Internally, it is a *process graph* with a variety of additional metadata.\n\nA **process graph** chains specific process calls from the set of predefined and user-defined processes together. A process graph itself can be stored as a (user-defined) process again. Similarly to scripts in the context of programming, process graphs organize and automate the execution of one or more processes that could alternatively be executed individually. In a process graph, processes need to be specific, i.e. concrete values or \"placeholders\" for input parameters need to be specified. These values can be scalars, arrays, objects, references to parameters or previous computations or other process graphs.\n\n## Defining Processes\n\nBack-ends and users MAY define new proprietary processes for their domain. \n\n**Back-end providers** MUST follow the schema for predefined processes as in [`GET /processes`](#operation/list-processes) to define new processes. This includes:\n\n* Choosing a intuitive process id, consisting of only letters (a-z), numbers and underscores. It MUST be unique across the predefined processes.\n* Defining the parameters and their exact (JSON) schemes.\n* Specifying the return value of a process also with a (JSON) schema.\n* Providing examples or compliance tests.\n* Trying to make the process universally usable so that other back-end providers or openEO can adopt it.\n\n**Users** MUST follow the schema for user-defined processes as in [`GET /process_graphs/{process_graph_id}`](#operation/describe-custom-process) to define new processes. This includes:\n\n* Choosing a intuitive name as process id, consisting of only letters (a-z), numbers and underscores. It MUST be unique per user across the user-defined processes.\n* Defining the algorithm as a process graph.\n* Optionally, specifying the additional metadata for processes.\n\nIf new process are potentially useful for other back-ends the openEO consortium is happily accepting [pull requests](https://github.com/Open-EO/openeo-processes/pulls) to include them in the list of predefined processes.\n\n### Schemas\n\nEach process parameter and the return values of a process define a schema that the value MUST comply to. The schemas are based on [JSON Schema draft-07](http://json-schema.org/).\n\nMultiple custom keywords have been defined:\n* `subtype` for more fine-grained data-types than JSON Schema supports.\n* `dimensions` to further define the dimension types required if the `subtype` is `datacube`.\n* `parameters` to specify the parameters of a process graph if the `subtype` is `process-graph`.\n* `returns` to describe the return value of a process graph if the `subtype` is `process-graph`.\n\n### Subtypes\n\nJSON Schema allows to specify only a small set of native data types (string, boolean, number, integer, array, object, null).\nTo support more fine grained data types, a custom [JSON Schema keyword](https://json-schema.org/draft-07/json-schema-core.html#rfc.section.6.4) has been defined: `subtype`.\nIt works similarly as the JSON Schema keyword [`format`](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.7)\nand standardizes a number of openEO related data types that extend the native data types, for example:\n`bounding-box` (object with at least `west`, `south`, `east` and `north` properties),\n`date-time` (string representation of date and time following RFC 3339),\n`datacube` (a datacube with dimensions), etc.\nThe subtypes should be re-used in process schema definitions whenever suitable.\n\nIf a general data type such as `string` or `number` is used in a schema, all subtypes with the same parent data type can be passed, too.\nClients should offer make passing subtypes as easy as passing a general data type.\nFor example, a parameter accepting strings must also allow passing a string with subtype `date` and thus clients should encourage this by also providing a date-picker.\n\nA list of predefined subtypes is available as JSON Schema in [openeo-processes](https://github.com/Open-EO/openeo-processes).\n\n## Process Graphs\n\nAs defined above, a **process graph** is a chain of processes with explicit values for their parameters.\nTechnically, a process graph is defined to be a graph of connected processes with exactly one node returning the final result:\n\n```\n := {\n \"\": ,\n ...\n}\n```\n\n`` is a unique key within the process graph that is used to reference (the return value of) this process in arguments of other processes. The identifier is unique only strictly within itself, excluding any parent and child process graphs. Process node identifiers are also strictly scoped and can not be referenced from child or parent process graphs. Circular references are not allowed.\n\nNote: We provide a non-binding [JSON Schema for basic process graph validation](assets/pg-schema.json).\n\n### Processes (Process Nodes)\n\nA single node in a process graph (i.e. a specific instance of a process) is defined as follows:\n\n```\n := {\n \"process_id\": ,\n \"namespace\": / null,\n \"description\": ,\n \"arguments\": ,\n \"result\": true / false\n}\n```\nA process node MUST always contain key-value-pairs named `process_id` and `arguments`. It MAY contain a `description`.\n\nOne of the nodes in a map of processes (the final one) MUST have the `result` flag set to `true`, all the other nodes can omit it as the default value is `false`. Having such a node is important as multiple end nodes are possible, but in most use cases it is important to exactly specify the return value to be used by other processes. Each child process graph must also specify a result node similar to the \"main\" process graph.\n\n`process_id` MUST be a valid process ID in the `namespace` given. Clients SHOULD warn the user if a user-defined process is added with the same identifier as one of the predefined process.\n\n### Arguments\n\nA process can have an arbitrary number of arguments. Their name and value are specified \nin the process specification as an object of key-value pairs:\n\n```\n := {\n \"\": \n}\n```\n\n**Notes:**\n- The specified data types are the native data types supported by JSON, except for `ResultReference`, `UserDefinedProcess` and `ParameterReference`.\n- Objects are not allowed to have keys with the following reserved names:\n\n * `from_node`, except for objects of type `ResultReference`\n * `process_graph`, except for objects of type `UserDefinedProcess`\n * `from_parameter`, except for objects of type `ParameterReference`\n\n- Arrays and objects can also contain a `ResultReference`, a `UserDefinedProcess` or a `ParameterReference`. So back-ends must *fully* traverse the process graphs, including all children.\n\n### Accessing results of other process nodes\n\nA value of type `` is an object with a key `from_node` and a `` as corresponding value:\n\n```\n := {\n \"from_node\": \"\"\n}\n```\n\nThis tells the back-end that the process expects the result (i.e. the return value) from another process node to be passed as argument.\nThe `` is strictly scoped and can only reference nodes from within the same process graph, not child or parent process graphs.\n\n### Child processes\n\nSome processes can run child processes, which is similar to the concept that other programming languages call\n[callbacks](https://en.wikipedia.org/wiki/Callback_(computer_programming)) or lambda functions.\nEach child process is simply a user-defined process again and can in theory be arbritarily complex.\n\nA very simple example would be to calculate the absolute value of each pixel in a data cube.\nThis can be achieved in openEO by using the `apply` process which gets the `absolute` process passed as child process.\nIn this example, the \"child\" processes consists of a single process `absolute`, but it can also be a more complex computation such as an NDVI or a prediciton based on a machine learning model.\n\n**Example**: \n\nA `` argument MUST at least consist of an object with a key `process_graph`.\nOptionally, it can also be described with the same additional properties available for predefined processes such as an id, parameters, return values etc.\nWhen embedded in a process graph, these additional properties of a user-defined process are usually not used, except for validation purposes.\n\n```\n := {\n \"process_graph\": ,\n ...\n}\n```\n\n### Accessing process parameters\n\nA \"parent\" process that works with a child process can make so called *process graph parameters*\navailable to the \"child\" logic.\nProcesses in the \"child\" process graph can access these parameters by passing a `ParameterReference` object as argument.\nIt is an object with key `from_parameter` specifying the name of the process graph parameter:\n\n```\n := {\n \"from_parameter\": \"\"\n}\n```\n\nThe parameter names made available for `` are defined and passed to the process graph by one of the parent entities.\nThe parent could be a process (such as `apply` or `reduce_dimension`) or something else that executes a process graph (a secondary web service for example).\nIf the parent is a process, the parameter are defined in the [`parameters` property](#section/Processes/Defining-Processes) of the corresponding JSON Schema.\n\nIn case of the example given above, the parameter `process` in the process [`apply`](https://processes.openeo.org/#apply) defines two process graph parameters: `x` (the value of each pixel that will be processed) and `context` (additional data passed through from the user).\nThe process `absolute` expects an argument with the same name `x`.\nThe process graph for the example would look as follows:\n\n```\n{\n \"process_id\": \"apply\",\n \"arguments\": {\n \"data\": {\"from_node\": \"loadcollection1\"}\n \"process\": {\n \"process_graph\": {\n \"abs1\": {\n \"process_id\": \"absolute\",\n \"arguments\": {\n \"x\": {\"from_parameter\": \"x\"}\n },\n \"result\": true\n }\n }\n }\n }\n}\n```\n\n`loadcollection1` would be a result from another process, which is not part of this example.\n\n**Important:** `` is less strictly scoped than ``.\n`` can be any parameter from the process graph or any of its parents.\n\nThe value for the parameter MUST be resolved as follows:\n1. In general the most specific parameter value is used. This means the parameter value is resolved starting from the current scope and then checking each parent for a suitable parameter value until a parameter values is found or the \"root\" process graph has been reached.\n2. In case a parameter value is not available, the most unspecific default value from the process graph parameter definitions are used. For example, if default values are available for the root process graph and all children, the default value from the root process graph is used.\n3. If no default values are available either, the error `ProcessParameterMissing` must be thrown.\n\n### Full example for an EVI computation\n\nDeriving minimum EVI (Enhanced Vegetation Index) measurements over pixel time series of Sentinel 2 imagery. The main process graph in blue, child process graphs in yellow:\n\n![Graph with processing instructions](assets/pg-evi-example.png)\n\nThe process graph for the algorithm: [pg-evi-example.json](assets/pg-evi-example.json)\n\n## Data Processing\n\nProcesses can run in three different ways:\n\n1. Results can be pre-computed by creating a ***batch job***. They are submitted to the back-end's processing system, but will remain inactive until explicitly put into the processing queue. They will run only once and store results after execution. Results can be downloaded. Batch jobs are typically time consuming and user interaction is not possible although log files are generated for them. This is the only mode that allows to get an estimate about time, volume and costs beforehand.\n\n2. A more dynamic way of processing and accessing data is to create a **secondary web service**. They allow web-based access using different protocols such as [OGC WMS](http://www.opengeospatial.org/standards/wms), [OGC WCS](http://www.opengeospatial.org/standards/wcs), [OGC API - Features](https://www.ogc.org/standards/ogcapi-features) or [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames). Some protocols such as the OGC WMS or XYZ tiles allow users to change the viewing extent or level of detail (zoom level). Therefore, computations often run *on demand* so that the requested data is calculated during the request. Back-ends should make sure to cache processed data to avoid additional/high costs and reduce waiting times for the user.\n\n3. Processes can also be executed **on-demand** (i.e. synchronously). Results are delivered with the request itself and no job is created. Only lightweight computations, for example previews, should be executed using this approach as timeouts are to be expected for [long-polling HTTP requests](https://www.pubnub.com/blog/2014-12-01-http-long-polling/).\n\n### Validation\n\nProcess graph validation is a quite complex task. There's a [JSON schema](assets/pg-schema.json) for basic process graph validation. It checks the general structure of a process graph, but only checking against the schema is not fully validating a process graph. Note that this JSON Schema is probably good enough for a first version, but should be revised and improved for production. There are further steps to do:\n\n1. Validate whether there's exactly one `result: true` per process graph.\n2. Check whether the process names that are referenced in the field `process_id` are actually available in the corresponding `namespace`.\n3. Validate all arguments for each process against the JSON schemas that are specified in the corresponding process specifications.\n4. Check whether the values specified for `from_node` have a corresponding node in the same process graph.\n5. Validate whether the return value and the arguments requesting a return value with `from_node` are compatible.\n7. Check the content of arrays and objects. These could include parameter and result references (`from_node`, `from_parameter` etc.).\n\n\n### Execution\n\nTo process the process graph on the back-end you need to go through all nodes/processes in the list and set for each node to which node it passes data and from which it expects data. In another iteration the back-end can find all start nodes for processing by checking for zero dependencies.\n\nYou can now start and execute the start nodes (in parallel, if possible). Results can be passed to the nodes that were identified beforehand. For each node that depends on multiple inputs you need to check whether all dependencies have already finished and only execute once the last dependency is ready.\n\nPlease be aware that the result node (`result` set to `true`) is not necessarily the last node that is executed. The author of the process graph may choose to set a non-end node to the result node!", - "contact": { - "name": "openEO Consortium", - "url": "https://openeo.org", - "email": "openeo.psc@uni-muenster.de" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - } - }, - "externalDocs": { - "description": "openEO Documentation", - "url": "https://openeo.org/documentation/1.0/" - }, - "tags": [ - { - "name": "Capabilities", - "description": "General information about the API implementation and other supported capabilities at the back-end." - }, - { - "name": "Account Management", - "description": "The following endpoints handle user profiles, accounting and authentication. See also [Authentication](#section/Authentication). In general, the openEO API only defines a minimum subset of user management and accounting functionality. It allows to\n\n* [authenticate and authorize](http://www.differencebetween.net/technology/difference-between-authentication-and-authorization/) a user, which may include [user registration with OpenID Connect](http://openid.net/specs/openid-connect-registration-1_0.html),\n* handle storage space limits (disk quota),\n* manage billing, which includes to\n * query the credit a user has available,\n * estimate costs for certain operations (data processing and downloading),\n * get information about produced costs,\n * limit costs of certain operations.\n\nTherefore, the API leaves some aspects open that have to be handled by the back-ends separately, including \n\n* credentials recovery, e.g. retrieving a forgotten password\n* user data management, e.g. changing the users payment details or email address\n* payments, i.e. topping up credits for pre-paid services or paying for post-paid services\n* other accounting related tasks, e.g. creating invoices,\n* user registration (except for [user registration with OpenID Connect](http://openid.net/specs/openid-connect-registration-1_0.html))." - }, - { - "name": "EO Data Discovery", - "description": "These endpoints allow to list the collections that are available at the back-end and can be used as data cubes for data processing.\n\n## STAC\n\nFor data discovery of Earth Observation Collections at the back-ends, openEO strives for compatibility with the specifications [SpatioTemporal Asset Catalog (STAC)](https://stacspec.org/) and [OGC API - Features - Part 1: Core](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html) as far as possible. Implementing the data discovery endpoints of openEO also produced valid STAC API 1.0 and OGC API - Features 1.0 responses, including ([partial](#provide-data-for-download)) compatibility with their APIs. \n\nThe data discovery endpoints `GET /collections` and `GET /collections/{collection_id}` are compatible with OGC API - Features and STAC. Both specifications define additional endpoints that need to be implemented to be fully compatible. The additional endpoints can easily be integrated into an openEO API implementation. A rough list of actions for compatibility is available below, but please refer to their specifications to find out the full details.\n\n**Important:** [STAC specification](https://github.com/radiantearth/stac-spec) and [STAC API](https://github.com/radiantearth/stac-api-spec) are different specifications and have different version numbers after version 0.9.0.\nThe openEO API implements STAC API versions >= 0.9.0 (preferrably [STAC API version 1.0.0](https://github.com/radiantearth/stac-api-spec/blob/v1.0.0/README.md), but [0.9.0](https://github.com/radiantearth/stac-spec/blob/v0.9.0/api-spec/README.md) is allowed for backward compatibility), which allows to serve all STAC specification versions in the range of 0.9.x and 1.x.x (see the `stac_version` property).\n\n### Content Extensions\n\nSTAC has several [extensions](https://stac-extensions.github.io) that can be used to better describe your data. Clients and server are not required to implement all of them, so be aware that some clients may not be able to read all your metadata.\n\nSome commonly used extensions that are relevant for datasets exposed through the openEO API are:\n\n- Data Cube extension (part of the openEO API)\n- [EO (Electro-Optical) extension](https://github.com/stac-extensions/eo)\n- [Processing extension](https://github.com/stac-extensions/processing)\n- [Raster extension](https://github.com/stac-extensions/raster)\n- [SAR extension](https://github.com/stac-extensions/sar)\n- [Satellite extension](https://github.com/stac-extensions/sat)\n- [Scientific Citation extension](https://github.com/stac-extensions/scientific)\n\n### Provide data for download\n\nIf you'd like to provide your data for download in addition to offering the cloud processing service, you can implement the full STAC API. Therefore you can implement the endpoints `GET /collections/{collection_id}/items` and `GET /collections/{collection_id}/items/{feature_id}` to support retrieval of individual items. To benefit from the STAC ecosystem and allow searching for items you can also implement `POST /search` and `GET /search`. Further information can be found in the [STAC API repository](https://github.com/radiantearth/stac-spec/tree/v0.9.0/api-spec).\n\n### API Extensions\n\nSTAC API has several [extensions](https://stac-api-extensions.github.io) that can be implemented on top of the openEO API to enrich the API functionality, e.g. for searching." - }, - { - "name": "Process Discovery", - "description": "These endpoints allow to list the predefined processes that are available at the back-end. To list user-defined processes see '[User-Defined Processes](#tag/User-Defined-Processes)'." - }, - { - "name": "User-Defined Processes", - "description": "These endpoints allow to store and manage user-defined processes with their process graphs at the back-end." - }, - { - "name": "Data Processing", - "description": "Organizes and manages data processing on the back-end, either as synchronous on-demand computation or batch jobs." - }, - { - "name": "Batch Jobs", - "description": "Management of batch processing tasks (jobs) and their results." - }, - { - "name": "Secondary Services", - "description": "On-demand access to data using other web service protocols." - }, - { - "name": "File Storage", - "description": "Management of user-uploaded assets and processed data." - } - ], - "servers": [ - { - "url": "https://openeo.example/api/{version}", - "description": "The URL of the API MAY freely be chosen by the back-end providers. The path, including API versioning, is a *recommendation* only. Nevertheless, all servers MUST support HTTPS as the authentication methods are not secure with HTTP only!", - "variables": { - "version": { - "default": "v1", - "description": "API versioning is RECOMMENDED. As the openEO API is following\n[SemVer](https://semver.org/) only the **major** part of the version\nnumbers SHOULD be used for API versioning in the URL. To make clear\nthat it is a version number, it is RECOMMENDED to add the prefix `v`.\n\nExample: API version `1.2.3` is recommended to use `v1`.\n\nThe reason to only consider the major part is that backward-incompatible\nchanges are introduced by major changes only. All changes from minor\nand patch releases can usually be integrated without breakages and thus\na change in the URL is not really needed.\n\nThe version number in the URL MUST not be used by the clients to detect\nthe version number of the API. Use the version number returned in the\nproperty `api_version` from `GET /` instead." - } - } - } - ], - "paths": { - "/": { - "get": { - "summary": "Information about the back-end", - "operationId": "capabilities", - "description": "Lists general information about the back-end, including which version and endpoints of the openEO API are supported. May also include billing information.", - "tags": [ - "Capabilities" - ], - "security": [ - {} - ], - "responses": { - "200": { - "description": "Information about the API version and supported endpoints /\nfeatures.\n\nThis endpoint MUST always be available for the API to be valid.", - "content": { - "application/json": { - "schema": { - "title": "Capabilities", - "type": "object", - "required": [ - "id", - "title", - "description", - "api_version", - "backend_version", - "stac_version", - "endpoints", - "links" - ], - "properties": { - "api_version": { - "type": "string", - "description": "Version number of the openEO specification this back-end implements.", - "enum": [ - "1.2.0" - ] - }, - "backend_version": { - "type": "string", - "description": "Version number of the back-end implementation.\nEvery change on back-end side MUST cause a change of the version number.", - "example": "1.1.2" - }, - "stac_version": { - "$ref": "#/components/schemas/stac_version" - }, - "type": { - "type": "string", - "enum": [ - "Catalog" - ], - "description": "For STAC versions >= 1.0.0-rc.1 this field is required.", - "example": "Catalog" - }, - "id": { - "type": "string", - "description": "Identifier for the service.\nThis field originates from STAC and is used as unique identifier for the STAC catalog available at `/collections`.", - "example": "cool-eo-cloud" - }, - "title": { - "type": "string", - "description": "The name of the service.", - "example": "Example Cloud Corp." - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "A description of the service, which allows the service provider to introduce the user to its service.\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", - "example": "This service is provided to you by [Example Cloud Corp.](https://cloud.example). It implements the full openEO API and allows to process a range of 999 EO data sets, including \n\n* Sentinel 1/2/3 and 5\n* Landsat 7/8\n\nA free plan is available to test the service. For further information please contact our customer service at [support@cloud.example](mailto:support@cloud.example)." - }, - "conformsTo": { - "$ref": "#/components/schemas/conformsTo" - }, - "production": { - "$ref": "#/components/schemas/production" - }, - "endpoints": { - "type": "array", - "description": "Lists all supported endpoints. Supported are all endpoints, which are implemented, return usually a 2XX or 3XX HTTP status code and are fully compatible to the API specification. An entry for this endpoint (path `/` with method `GET`) SHOULD NOT be listed. Each path MUST only be listed once in the array.", - "items": { - "title": "Endpoint", - "type": "object", - "required": [ - "path", - "methods" - ], - "properties": { - "path": { - "description": "Path to the endpoint, relative to the URL of this endpoint. In general the paths MUST follow the paths specified in the openAPI specification as closely as possible. Therefore, paths MUST be prepended with a leading slash, but MUST NOT contain a trailing slash. Variables in the paths MUST be placed in curly braces and follow the parameter names in the openAPI specification, e.g. `{job_id}`.", - "type": "string" - }, - "methods": { - "description": "Supported HTTP verbs in uppercase. It is OPTIONAL to list `OPTIONS` as method (see the [CORS section](#section/Cross-Origin-Resource-Sharing-(CORS))).", - "type": "array", - "items": { - "type": "string", - "enum": [ - "GET", - "POST", - "PATCH", - "PUT", - "DELETE", - "OPTIONS" - ] - } - } - } - }, - "example": [ - { - "path": "/collections", - "methods": [ - "GET" - ] - }, - { - "path": "/collections/{collection_id}", - "methods": [ - "GET" - ] - }, - { - "path": "/processes", - "methods": [ - "GET" - ] - }, - { - "path": "/jobs", - "methods": [ - "GET", - "POST" - ] - }, - { - "path": "/jobs/{job_id}", - "methods": [ - "GET", - "DELETE", - "PATCH" - ] - } - ] - }, - "billing": { - "title": "Billing", - "description": "Billing related data, e.g. the currency used or available plans to process jobs.\nThis property MUST be specified if the back-end uses any billing related API functionalities, e.g. budgeting or estimates.\nThe absence of this property doesn't mean the back-end is necessarily free to use for all. Providers may choose to bill users outside of the API, e.g. with a monthly fee that is not depending on individual API interactions.", - "type": "object", - "required": [ - "currency" - ], - "properties": { - "currency": { - "description": "The currency the back-end is billing in. The currency MUST be either a valid currency code as defined in ISO-4217 or a back-end specific unit that is used for billing such as credits, tiles or CPU hours. If set to `null`, budget and costs are not supported by the back-end and users can't be charged.", - "type": "string", - "nullable": true, - "example": "USD" - }, - "default_plan": { - "type": "string", - "description": "Name of the plan the back-end uses for billing in case \n1. the user has not subscribed to a specific plan\n (see `default_plan` in `GET /me`) and\n2. also did not provide a specific plan with the\n processing request.\n\nIf a free plan is available at the back-end, it is \nprobably most useful to provide this as the back-end\nwide default plan and override it with paid plans through\nthe user-specific default plan in `GET /me`.\nOtherwise, users that have not set up payment yet MAY\nreceive an error for each processing requests where\nthey did not provide a free plan specifically.", - "example": "free" - }, - "plans": { - "description": "Array of plans", - "type": "array", - "items": { - "title": "Billing Plan", - "type": "object", - "required": [ - "name", - "description", - "paid" - ], - "properties": { - "name": { - "type": "string", - "description": "Name of the plan. It MUST be accepted in a *case insensitive* manner throughout the API.", - "example": "free" - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "A description that gives a rough overview over the plan.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", - "example": "Free plan for testing." - }, - "paid": { - "type": "boolean", - "description": "Indicates whether the plan is a paid plan (`true`) or a free plan (`false`)." - }, - "url": { - "type": "string", - "description": "URL to a web page with more details about the plan.", - "format": "uri", - "example": "https://cloud.example/plans/free-plan" - } - } - }, - "example": [ - { - "name": "free", - "description": "Free plan. Calculates one tile per second and a maximum amount of 100 tiles per hour.", - "url": "https://cloud.example/plans/free-plan", - "paid": false - }, - { - "name": "premium", - "description": "Premium plan. Calculates unlimited tiles and each calculated tile costs 0.003 USD.", - "url": "https://cloud.example/plans/premium-plan", - "paid": true - } - ] - } - } - }, - "links": { - "description": "Links related to this service, e.g. the homepage of\nthe service provider or the terms of service.\n\nIt is highly RECOMMENDED to provide links with the\nfollowing `rel` (relation) types:\n\n1. `version-history`: A link back to the Well-Known URL\n(including `/.well-known/openeo`, see the corresponding endpoint for details)\nto allow clients to work on the most recent version.\n\n2. `terms-of-service`: A link to the terms of service. If\na back-end provides a link to the terms of service, the\nclients MUST provide a way to read the terms of service\nand only connect to the back-end after the user agreed to\nthem. The user interface MUST be designed in a way that\nthe terms of service are not agreed to by default, i.e.\nthe user MUST explicitly agree to them.\n\n3. `privacy-policy`: A link to the privacy policy (GDPR).\nIf a back-end provides a link to a privacy policy, the\nclients MUST provide a way to read the privacy policy and\nonly connect to the back-end after the user agreed to\nthem. The user interface MUST be designed in a way that\nthe privacy policy is not agreed to by default, i.e. the\nuser MUST explicitly agree to them.\n\n4. `service-desc` or `service-doc`: A link to the API definition.\nUse `service-desc` for machine-readable API definition and \n`service-doc` for human-readable API definition.\nRequired if full OGC API compatibility is desired.\n\n5. `conformance`: A link to the Conformance declaration\n(see `/conformance`). \nRequired if full OGC API compatibility is desired.\n\n6. `data`: A link to the collections (see `/collections`).\nRequired if full OGC API compatibility is desired.\n\n7. `create-form`: A link to a user registration page.\n\n8. `recovery-form`: A link to a page where a user can\nrecover a user account (e.g. to reset the password or send\na reminder about the username to the user's email account).\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "href": "https://cloud.example", - "rel": "about", - "type": "text/html", - "title": "Homepage of the service provider" - }, - { - "href": "https://cloud.example/tos", - "rel": "terms-of-service", - "type": "text/html", - "title": "Terms of Service" - }, - { - "href": "https://cloud.example/privacy", - "rel": "privacy-policy", - "type": "text/html", - "title": "Privacy Policy" - }, - { - "href": "https://cloud.example/register", - "rel": "create-form", - "type": "text/html", - "title": "User Registration" - }, - { - "href": "https://cloud.example/lost-password", - "rel": "recovery-form", - "type": "text/html", - "title": "Reset Password" - }, - { - "href": "https://cloud.example/.well-known/openeo", - "rel": "version-history", - "type": "application/json", - "title": "List of supported openEO versions" - }, - { - "href": "https://cloud.example/api/v1/conformance", - "rel": "conformance", - "type": "application/json", - "title": "OGC Conformance Classes" - }, - { - "href": "https://cloud.example/api/v1/collections", - "rel": "data", - "type": "application/json", - "title": "List of Datasets" - } - ] - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/.well-known/openeo": { - "get": { - "summary": "Supported openEO versions", - "operationId": "connect", - "description": "Lists all implemented openEO versions supported by the\nservice provider. This endpoint is the Well-Known URI\n(see [RFC 5785](https://www.rfc-editor.org/rfc/rfc5785.html)) for openEO.\n\nThis allows a client to easily identify the most recent openEO\nimplementation it supports. By default, a client SHOULD connect to the\nmost recent production-ready version it supports. If not available, the\nmost recent supported version of *all* versions SHOULD be connected to.\nClients MAY let users choose to connect to versions that are not\nproduction-ready or outdated.\nThe most recent version is determined by comparing the version numbers\naccording to rules from [Semantic Versioning](https://semver.org/),\nespecially [§11](https://semver.org/#spec-item-11). Any pair of API\nversions in this list MUST NOT be equal according to Semantic Versioning.\n\nThe Well-Known URI is the entry point for clients and users, so make\nsure it is permanent and easy to use and remember. Clients MUST NOT\nrequire the well-known path (`/.well-known/openeo`) in the URL that is\nspecified by a user to connect to the back-end.\n\nFor clients, the usual behavior SHOULD follow these steps:\n1. The user provides a URI, which may consist of a scheme (protocol), \n an authority (host, port) and a path.\n2. The client parses the URI and appends `/.well-knwon/openeo` to the\n path. Make sure to correctly handle leading/trailing slashes.\n3. Send a request to the new URI.\n A. On success: Detect the most suitable API instance/version (see above)\n and read the [capabilites](#tag/Capabilities/operation/capabilities)\n from there.\n B. On failure: Directly try to read the capabilities from the original URI\n given by the user.\n\n**This URI MUST NOT be versioned as the other endpoints.**\nIf your API is available at `https://openeo.example/api/v1`, and\nyou instruct your API users to use `https://openeo.example` as connection URI, \nthe Well-Known URI SHOULD be located at `https://openeo.example/.well-known/openeo`.\nThe Well-Known URI is usually directly located at the top-level, but it is not a\nrequirement. For example, `https://openeo.example/eo/.well-known/openeo` is also allowed.\n\nClients MAY get additional information (e.g. title or description) about\na back-end from the most recent version that has the `production` flag\nset to `true`.", - "tags": [ - "Capabilities" - ], - "security": [ - {} - ], - "servers": [ - { - "url": "https://openeo.example", - "description": "The Well-Known URI SHOULD be available directly at `https://{{domain}}/.well-known/openeo` in contrast to the other endpoints, which may be versioned and can run on other hosts, ports, ... etc." - } - ], - "responses": { - "200": { - "description": "List of all available API instances, each with URL and the implemented openEO API version.", - "content": { - "application/json": { - "schema": { - "title": "Well Known Discovery", - "type": "object", - "required": [ - "versions" - ], - "properties": { - "versions": { - "type": "array", - "items": { - "title": "API Instance", - "type": "object", - "required": [ - "url", - "api_version" - ], - "properties": { - "url": { - "type": "string", - "format": "uri", - "description": "*Absolute* URLs to the service.", - "example": "https://openeo.example/api/v1" - }, - "production": { - "$ref": "#/components/schemas/production" - }, - "api_version": { - "type": "string", - "description": "Version number of the openEO specification this back-end implements." - } - } - } - } - } - }, - "example": { - "versions": [ - { - "url": "https://openeo.example/api/v0", - "api_version": "0.5.1" - }, - { - "url": "https://openeo.example/api/v1", - "api_version": "1.2.0" - }, - { - "url": "https://dev.openeo.example/api/v2", - "production": false, - "api_version": "2.0.0-beta" - } - ] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/file_formats": { - "get": { - "summary": "Supported file formats", - "operationId": "list-file-types", - "description": "Lists supported input and output file formats.\n*Input* file formats specify which file a back-end can *read* from.\n*Output* file formats specify which file a back-end can *write* to.\n\nThe response to this request is an object listing all available input\nand output file formats separately with their parameters and additional\ndata. This endpoint does not include the supported secondary web\nservices.\n\n**Note**: Format names and parameters MUST be fully aligned with the\nGDAL codes if available, see [GDAL Raster\nFormats](https://gdal.org/drivers/raster/index.html) and [OGR Vector\nFormats](https://gdal.org/drivers/vector/index.html). It is OPTIONAL to\nsupport all output format parameters supported by GDAL. Some file\nformats not available through GDAL may be defined centrally for openEO.\nCustom file formats or parameters MAY be defined.\n\nThe format descriptions must describe how the file formats relate to \ndata cubes. Input file formats must describe how the files have to be\nstructured to be transformed into data cubes. Output file formats must\ndescribe how the data cubes are stored at the back-end and how the \nresulting file structure looks like.\n\nBack-ends MUST NOT support aliases, for example it is not allowed to\nsupport `geotiff` instead of `gtiff`. Nevertheless, openEO Clients MAY\ntranslate user input input for convenience (e.g. translate `geotiff` to\n`gtiff`). Also, for a better user experience the back-end can specify a\n`title`.\n\nFormat names MUST be accepted in a *case insensitive* manner throughout the API.", - "tags": [ - "Capabilities", - "Data Processing" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "An object with containing all input and output format separately. For each property `input` and `output` an object is defined where the file format names are the property keys and the property values are objects that define a title, supported parameters and related links.", - "content": { - "application/json": { - "schema": { - "title": "File Formats", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "title": "Input File Formats", - "type": "object", - "description": "Map of supported input file formats, i.e. file formats a back-end can **read** from. The property keys are the file format names that are used by clients and users, for example in process graphs.", - "additionalProperties": { - "$ref": "#/components/schemas/file_format" - } - }, - "output": { - "title": "Output File Formats", - "type": "object", - "description": "Map of supported output file formats, i.e. file formats a back-end can **write** to. The property keys are the file format names that are used by clients and users, for example in process graphs.", - "additionalProperties": { - "$ref": "#/components/schemas/file_format" - } - } - } - }, - "example": { - "output": { - "GTiff": { - "title": "GeoTiff", - "description": "Export to GeoTiff. Doesn't support cloud-optimized GeoTiffs (COGs) yet.", - "gis_data_types": [ - "raster" - ], - "parameters": { - "tiled": { - "type": "boolean", - "description": "This option can be used to force creation of tiled TIFF files [true]. By default [false] stripped TIFF files are created.", - "default": false - }, - "compress": { - "type": "string", - "description": "Set the compression to use.", - "default": "NONE", - "enum": [ - "JPEG", - "LZW", - "DEFLATE", - "NONE" - ] - }, - "jpeg_quality": { - "type": "integer", - "description": "Set the JPEG quality when using JPEG.", - "minimum": 1, - "maximum": 100, - "default": 75 - } - }, - "links": [ - { - "href": "https://gdal.org/drivers/raster/gtiff.html", - "rel": "about", - "title": "GDAL on the GeoTiff file format and storage options" - } - ] - }, - "GPKG": { - "title": "OGC GeoPackage", - "gis_data_types": [ - "raster", - "vector" - ], - "parameters": { - "version": { - "type": "string", - "description": "Set GeoPackage version. In AUTO mode, this will be equivalent to 1.2 starting with GDAL 2.3.", - "enum": [ - "auto", - "1", - "1.1", - "1.2" - ], - "default": "auto" - } - }, - "links": [ - { - "href": "https://gdal.org/drivers/raster/gpkg.html", - "rel": "about", - "title": "GDAL on GeoPackage for raster data" - }, - { - "href": "https://gdal.org/drivers/vector/gpkg.html", - "rel": "about", - "title": "GDAL on GeoPackage for vector data" - } - ] - } - }, - "input": { - "GPKG": { - "title": "OGC GeoPackage", - "gis_data_types": [ - "raster", - "vector" - ], - "parameters": { - "table": { - "type": "string", - "description": "**RASTER ONLY.** Name of the table containing the tiles. If the GeoPackage dataset only contains one table, this option is not necessary. Otherwise, it is required." - } - }, - "links": [ - { - "href": "https://gdal.org/drivers/raster/gpkg.html", - "rel": "about", - "title": "GDAL on GeoPackage for raster data" - }, - { - "href": "https://gdal.org/drivers/vector/gpkg.html", - "rel": "about", - "title": "GDAL on GeoPackage for vector data" - } - ] - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/conformance": { - "get": { - "summary": "Conformance classes this API implements", - "operationId": "conformance", - "description": "Lists all conformance classes specified in various standards that the\nimplementation conforms to. Conformance classes are commonly used in\nall OGC APIs and the STAC API specification. openEO adds relatively\nbroadly defined conformance classes, especially for the extensions.\nOtherwise, the implemented functionality can usually be retrieved from\nthe [capabilties](#tag/Capabilities/operation/capabilities) in openEO.\n\nThe general openEO conformance class is `https://api.openeo.org/1.2.0`.\nSee the individual openEO API extensions for their conformance classes.\n\nThe conformance classes listed at this endpoint and listed in the \ncorresponding `conformsTo` property in `GET /` MUST be equal.\n\nMore details:\n- [STAC API](https://github.com/radiantearth/stac-api-spec), especially the conformance class \"STAC API - Collections\"\n- [OGC APIs](https://ogcapi.ogc.org/)", - "tags": [ - "Capabilities" - ], - "responses": { - "200": { - "description": "The URIs of all conformance classes supported by the server.", - "content": { - "application/json": { - "schema": { - "title": "OGC Conformance Classes", - "type": "object", - "required": [ - "conformsTo" - ], - "properties": { - "conformsTo": { - "$ref": "#/components/schemas/conformsTo" - } - } - } - } - } - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/collections": { - "get": { - "summary": "Basic metadata for all datasets", - "operationId": "list-collections", - "description": "Lists available collections with at least the required information.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting larger optional values from the objects in `collections` (e.g. the\n`summaries` and `cube:dimensions` properties).\nTo get the full metadata for a collection clients MUST\nrequest `GET /collections/{collection_id}`.\n\nThis endpoint is compatible with [STAC API 0.9.0 and later](https://stacspec.org) and\n[OGC API - Features 1.0](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html).\n[STAC API extensions](https://stac-api-extensions.github.io) and\n[STAC extensions](https://stac-extensions.github.io)\ncan be implemented in addition to what is documented here.\n\nNote: Although it is possible to request public collections without\nauthorization, it is RECOMMENDED that clients (re-)request the collections\nwith the Bearer token once available to also retrieve any private collections.", - "tags": [ - "EO Data Discovery" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Lists of collections and related links.", - "content": { - "application/json": { - "schema": { - "title": "Collections", - "type": "object", - "required": [ - "collections", - "links" - ], - "properties": { - "collections": { - "type": "array", - "items": { - "$ref": "#/components/schemas/collection" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - }, - "example": { - "collections": [ - { - "stac_version": "1.0.0", - "type": "Collection", - "id": "Sentinel-2A", - "title": "Sentinel-2A MSI L1C", - "description": "Sentinel-2A is a wide-swath, high-resolution, multi-spectral imaging mission supporting Copernicus Land Monitoring studies, including the monitoring of vegetation, soil and water cover, as well as observation of inland waterways and coastal areas.", - "license": "proprietary", - "extent": { - "spatial": { - "bbox": [ - [ - -180, - -56, - 180, - 83 - ] - ] - }, - "temporal": { - "interval": [ - [ - "2015-06-23T00:00:00Z", - "2019-01-01T00:00:00Z" - ] - ] - } - }, - "keywords": [ - "copernicus", - "esa", - "msi", - "sentinel" - ], - "providers": [ - { - "name": "European Space Agency (ESA)", - "roles": [ - "producer", - "licensor" - ], - "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" - }, - { - "name": "openEO", - "roles": [ - "host" - ], - "url": "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2" - } - ], - "links": [ - { - "rel": "license", - "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf" - } - ] - }, - { - "stac_version": "1.0.0", - "type": "Collection", - "id": "MOD09Q1", - "title": "MODIS/Terra Surface Reflectance 8-Day L3 Global 250m SIN Grid V006", - "description": "The MOD09Q1 Version 6 product provides an estimate of the surface spectral reflectance of Terra MODIS Bands 1-2 corrected for atmospheric conditions such as gasses, aerosols, and Rayleigh scattering. Provided along with the two 250 m MODIS bands is one additional layer, the Surface Reflectance QC 250 m band. For each pixel, a value is selected from all the acquisitions within the 8-day composite period. The criteria for the pixel choice include cloud and solar zenith. When several acquisitions meet the criteria the pixel with the minimum channel 3 (blue) value is used. Validation at stage 3 has been achieved for all MODIS Surface Reflectance products.", - "license": "proprietary", - "extent": { - "spatial": { - "bbox": [ - [ - -180, - -90, - 180, - 90 - ] - ] - }, - "temporal": { - "interval": [ - [ - "2000-02-01T00:00:00Z", - null - ] - ] - } - }, - "links": [ - { - "rel": "license", - "href": "https://openeo.example/api/v1/collections/MOD09Q1/license" - } - ] - } - ], - "links": [ - { - "rel": "alternate", - "href": "https://openeo.example/csw", - "title": "openEO catalog (OGC Catalogue Services 3.0)" - } - ] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/collections/{collection_id}": { - "get": { - "summary": "Full metadata for a specific dataset", - "operationId": "describe-collection", - "description": "Lists **all** information about a specific collection specified by the\nidentifier `collection_id`.\n\nThis endpoint is compatible with [STAC API 0.9.0 and later](https://stacspec.org) and\n[OGC API - Features 1.0](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html).\n[STAC API extensions](https://stac-api-extensions.github.io) and\n[STAC extensions](https://stac-extensions.github.io)\ncan be implemented in addition to what is documented here.\n\nNote: Providing the Bearer token is REQUIRED for private collections.", - "tags": [ - "EO Data Discovery" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/collection_id" - } - ], - "responses": { - "200": { - "description": "JSON object with the full collection metadata.", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "cube:dimensions", - "summaries" - ], - "allOf": [ - { - "$ref": "#/components/schemas/collection" - } - ] - }, - "example": { - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/datacube/v2.2.0/schema.json" - ], - "type": "Collection", - "id": "Sentinel-2", - "title": "Sentinel-2 MSI L2A", - "description": "Sentinel-2A is a wide-swath, high-resolution, multi-spectral imaging mission supporting Copernicus Land Monitoring studies.", - "license": "proprietary", - "keywords": [ - "copernicus", - "esa", - "msi", - "sentinel" - ], - "providers": [ - { - "name": "European Space Agency (ESA)", - "roles": [ - "producer", - "licensor" - ], - "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" - }, - { - "name": "Google", - "roles": [ - "host" - ], - "url": "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2" - } - ], - "extent": { - "spatial": { - "bbox": [ - [ - -180, - -56, - 180, - 83 - ] - ] - }, - "temporal": { - "interval": [ - [ - "2015-06-23T00:00:00Z", - null - ] - ] - } - }, - "links": [ - { - "rel": "license", - "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf", - "type": "application/pdf" - }, - { - "rel": "http://www.opengis.net/def/rel/ogc/1.0/queryables", - "href": "https://openeo.example/api/v1/collections/Sentinel-2A/queryables", - "type": "application/schema+json" - }, - { - "rel": "about", - "href": "https://earth.esa.int/web/sentinel/user-guides/sentinel-2-msi/product-types/level-1c", - "type": "text/html", - "title": "ESA Sentinel-2 MSI Level-1C User Guide" - }, - { - "rel": "example", - "href": "https://openeo.example/api/v1/collections/Sentinel-2/examples/true-color.json", - "type": "application/json", - "title": "Example Process for True-Color Visualization" - }, - { - "rel": "example", - "href": "https://openeo.example/api/v1/collections/Sentinel-2/examples/ndvi.json", - "type": "application/json", - "title": "Example Process for NDVI Calculation and Visualization" - } - ], - "cube:dimensions": { - "x": { - "type": "spatial", - "axis": "x", - "extent": [ - -180, - 180 - ], - "reference_system": 4326 - }, - "y": { - "type": "spatial", - "axis": "y", - "extent": [ - -56, - 83 - ], - "reference_system": 4326 - }, - "t": { - "type": "temporal", - "extent": [ - "2015-06-23T00:00:00Z", - null - ], - "step": null - }, - "bands": { - "type": "bands", - "values": [ - "B1", - "B2", - "B3", - "B4", - "B5", - "B6", - "B7", - "B8", - "B8A", - "B9", - "B10", - "B11", - "B12" - ] - } - }, - "summaries": { - "constellation": [ - "Sentinel-2" - ], - "platform": [ - "Sentinel-2A", - "Sentinel-2B" - ], - "instruments": [ - "MSI" - ], - "eo:cloud_cover": { - "minimum": 0, - "maximum": 75 - }, - "sat:orbit_state": [ - "ascending", - "descending" - ], - "gsd": [ - 10, - 20, - 60 - ], - "eo:bands": [ - { - "name": "B1", - "common_name": "coastal", - "center_wavelength": 0.4439, - "gsd": 60 - }, - { - "name": "B2", - "common_name": "blue", - "center_wavelength": 0.4966, - "gsd": 10 - }, - { - "name": "B3", - "common_name": "green", - "center_wavelength": 0.56, - "gsd": 10 - }, - { - "name": "B4", - "common_name": "red", - "center_wavelength": 0.6645, - "gsd": 10 - }, - { - "name": "B5", - "center_wavelength": 0.7039, - "gsd": 20 - }, - { - "name": "B6", - "center_wavelength": 0.7402, - "gsd": 20 - }, - { - "name": "B7", - "center_wavelength": 0.7825, - "gsd": 20 - }, - { - "name": "B8", - "common_name": "nir", - "center_wavelength": 0.8351, - "gsd": 10 - }, - { - "name": "B8A", - "common_name": "nir08", - "center_wavelength": 0.8648, - "gsd": 20 - }, - { - "name": "B9", - "common_name": "nir09", - "center_wavelength": 0.945, - "gsd": 60 - }, - { - "name": "B10", - "common_name": "cirrus", - "center_wavelength": 1.3735, - "gsd": 60 - }, - { - "name": "B11", - "common_name": "swir16", - "center_wavelength": 1.6137, - "gsd": 20 - }, - { - "name": "B12", - "common_name": "swir22", - "center_wavelength": 2.2024, - "gsd": 20 - } - ], - "proj:epsg": { - "minimum": 32601, - "maximum": 32660 - } - }, - "assets": { - "thumbnail": { - "href": "https://openeo.example/api/v1/collections/Sentinel-2/thumbnail.png", - "type": "image/png", - "title": "Preview", - "roles": [ - "thumbnail" - ] - }, - "inspire": { - "href": "https://openeo.example/api/v1/collections/Sentinel-2/inspire.xml", - "type": "application/xml", - "title": "INSPIRE metadata", - "description": "INSPIRE compliant XML metadata", - "roles": [ - "metadata" - ] - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/collections/{collection_id}/queryables": { - "get": { - "summary": "Metadata filters for a specific dataset", - "operationId": "list-collection-queryables", - "description": "Lists **all** supported metadata filters (also called \"queryables\") for\na specific collection.\n\nThis endpoint is compatible with endpoint defined in the STAC API extension\n[`filter`](https://github.com/stac-api-extensions/filter#queryables) and\n[OGC API - Features - Part 3: Filtering](https://github.com/opengeospatial/ogcapi-features/tree/master/extensions/filtering).\nFor a precise definition please follow those specifications.\n\nThis endpoints provides a JSON Schema for each queryable that openEO\nusers can use in multiple scenarios:\n1. For loading data from the collection, e.g. in the process `load_collection`.\n2. For filtering items using CQL2 on the `/collections/{collection_id}/items` endpoint\n (if [STAC API - Features is implemented in addition to the openEO API](#tag/EO-Data-Discovery/STAC)).\n\nNote: Providing the Bearer token is REQUIRED for private collections.", - "tags": [ - "EO Data Discovery" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/collection_id" - } - ], - "responses": { - "200": { - "description": "A JSON Schema defining the queryables.\n\nIt is RECOMMENDED to dereference all \"$refs\".", - "content": { - "application/schema+json": { - "schema": { - "$ref": "#/components/schemas/json_schema" - }, - "example": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://openeo.example/api/v1/collections/Sentinel-2A/queryables", - "type": "object", - "title": "Sentinel 2A", - "properties": { - "eo:cloud_cover": { - "title": "Cloud Cover", - "type": "number", - "minimum": 0, - "maximum": 100 - }, - "platform": { - "title": "Platform", - "description": "The satellite platform.", - "type": "string", - "enum": [ - "sentinel-2a", - "sentinel-2b" - ] - } - }, - "additionalProperties": false - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/processes": { - "get": { - "summary": "Supported predefined processes", - "operationId": "list-processes", - "description": "Lists all predefined processes and returns detailed process descriptions, including parameters and return values.", - "tags": [ - "Process Discovery" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Formal specification describing the supported predefined processes.", - "content": { - "application/json": { - "schema": { - "title": "Processes", - "type": "object", - "required": [ - "processes", - "links" - ], - "properties": { - "processes": { - "type": "array", - "items": { - "title": "Predefined Process", - "description": "A predefined process made available by the back-end.", - "type": "object", - "required": [ - "id", - "description", - "parameters", - "returns" - ], - "allOf": [ - { - "$ref": "#/components/schemas/process" - } - ] - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - }, - "example": { - "processes": [ - { - "id": "apply", - "summary": "Apply a process to each pixel", - "description": "Applies a *unary* process to each pixel value in the data cube (i.e. a local operation). A unary process takes a single value and returns a single value, for example ``abs()`` or ``linear_scale_range()``.", - "categories": [ - "cubes" - ], - "parameters": [ - { - "name": "data", - "description": "A data cube.", - "schema": { - "type": "object", - "subtype": "datacube" - } - }, - { - "name": "process", - "description": "A unary process to be applied on each value, may consist of multiple sub-processes.", - "schema": { - "type": "object", - "subtype": "process-graph", - "parameters": [ - { - "name": "x", - "description": "The value to process.", - "schema": { - "description": "Any data type." - } - } - ] - } - } - ], - "returns": { - "description": "A data cube with the newly computed values. The resolution, cardinality and the number of dimensions are the same as for the original data cube.", - "schema": { - "type": "object", - "subtype": "datacube" - } - } - }, - { - "id": "multiply", - "summary": "Multiplication of two numbers", - "description": "Multiplies the two numbers `x` and `y` (*x * y*) and returns the computed product.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", - "categories": [ - "math" - ], - "parameters": [ - { - "name": "x", - "description": "The multiplier.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - { - "name": "y", - "description": "The multiplicand.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The computed product of the two numbers.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "exceptions": { - "MultiplicandMissing": { - "message": "Multiplication requires at least two numbers." - } - }, - "examples": [ - { - "arguments": { - "x": 5, - "y": 2.5 - }, - "returns": 12.5 - }, - { - "arguments": { - "x": -2, - "y": -4 - }, - "returns": 8 - }, - { - "arguments": { - "x": 1, - "y": null - }, - "returns": null - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/Product.html", - "title": "Product explained by Wolfram MathWorld" - }, - { - "rel": "about", - "href": "https://ieeexplore.ieee.org/document/8766229", - "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" - } - ] - } - ], - "links": [ - { - "rel": "alternate", - "href": "https://openeo.example/processes", - "type": "text/html", - "title": "HTML version of the processes" - } - ] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/udf_runtimes": { - "get": { - "summary": "Supported UDF runtimes", - "operationId": "list-udf-runtimes", - "description": "Lists the supported runtimes for user-defined functions (UDFs), which includes either the programming languages including version numbers and available libraries including version numbers or docker containers.", - "tags": [ - "Capabilities" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Description of UDF runtime support", - "content": { - "application/json": { - "schema": { - "title": "UDF Runtimes", - "type": "object", - "description": "Map of available runtime environments. Runtime environments\ncan be either a programming language environment or Docker-based.\n\nEach runtime environment has a unique name, which is used as\nthe property key. The name is used in processes to select the\nruntime environment for UDFs, so the names should be stable and\nmeaningful.\nIt is RECOMMENDED to use the following naming and casing:\n* For programming langauge environments use the names as provided\n in in the [Scriptol List of Programming Languages](https://www.scriptol.com/programming/list-programming-languages.php).\n* For docker images use the docker image identifier excluding the registry path.", - "additionalProperties": { - "x-additionalPropertiesName": "UDF Runtime name", - "allOf": [ - { - "$ref": "#/components/schemas/udf_runtime" - } - ] - } - }, - "example": { - "PHP": { - "title": "PHP v7.x", - "description": "Just an example how to reference a docker image.", - "experimental": true, - "type": "docker", - "docker": "openeo/udf-php7", - "default": "latest", - "tags": [ - "latest", - "7.3.1", - "7.3", - "7.2" - ], - "links": [ - { - "href": "https://hub.docker.com/openeo/udf-php7/", - "rel": "about" - } - ] - }, - "R": { - "title": "R v3.x for Statistical Computing", - "description": "R programming language with `Rcpp` and `rmarkdown` extensions installed.", - "type": "language", - "default": "3.5.2", - "versions": { - "3.1.0": { - "deprecated": true, - "libraries": { - "Rcpp": { - "version": "1.0.10", - "links": [ - { - "href": "https://cran.r-project.org/web/packages/Rcpp/index.html", - "rel": "about" - } - ] - }, - "rmarkdown": { - "version": "1.7.0", - "links": [ - { - "href": "https://cran.r-project.org/web/packages/rmarkdown/index.html", - "rel": "about" - } - ] - } - } - }, - "3.5.2": { - "libraries": { - "Rcpp": { - "version": "1.2.0", - "links": [ - { - "href": "https://cran.r-project.org/web/packages/Rcpp/index.html", - "rel": "about" - } - ] - }, - "rmarkdown": { - "version": "1.7.0", - "links": [ - { - "href": "https://cran.r-project.org/web/packages/rmarkdown/index.html", - "rel": "about" - } - ] - } - } - } - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/credentials/oidc": { - "get": { - "summary": "OpenID Connect authentication", - "operationId": "authenticate-oidc", - "description": "Lists the supported [OpenID Connect](http://openid.net/connect/)\nproviders (OP). OpenID Connect Providers MUST support [OpenID Connect\nDiscovery](http://openid.net/specs/openid-connect-discovery-1_0.html).\n\nIt is highly RECOMMENDED to implement OpenID Connect for public services\nin favor of Basic authentication.\n\nopenEO clients MUST use the **access token** as part of the Bearer token\nfor authorization in subsequent API calls (see also the information\nabout Bearer tokens in this document). Clients MUST NOT use the id token\nor the authorization code. The access token provided by an OpenID Connect\nProvider does not necessarily provide information about the issuer (i.e. the\nOpenID Connect provider) and therefore a prefix MUST be added to the Bearer\nToken sent in subsequent API calls to protected endpoints. The Bearer\nToken sent to protected endpoints MUST consist of the authentication\nmethod (here `oidc`), the provider ID and the access token itself. All\nseparated by a forward slash `/`. The provider ID corresponds to the\nvalue specified for `id` for each provider in the response body of this\nendpoint. The header in subsequent API calls for a provider with `id`\n`ms` would look as follows: `Authorization: Bearer oidc/ms/TOKEN`\n(replace `TOKEN` with the actual access token received from the OpenID\nConnect Provider).\n\nBack-ends MAY request user information ([including Claims](https://openid.net/specs/openid-connect-core-1_0.html#Claims))\nfrom the [OpenID Connect Userinfo endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)\nusing the access token (without the prefix described above). Therefore,\nboth openEO client and openEO back-end are relying parties (clients) to\nthe OpenID Connect Provider.", - "tags": [ - "Account Management" - ], - "security": [ - {} - ], - "responses": { - "200": { - "description": "Lists the the OpenID Connect Providers.", - "content": { - "application/json": { - "schema": { - "title": "OpenID Connect Providers", - "type": "object", - "required": [ - "providers" - ], - "properties": { - "providers": { - "type": "array", - "description": "The first provider in this list is the default provider for authentication. Clients can either pre-select or directly use the default provider for authentication if the user doesn't specify a specific value.", - "minItems": 1, - "items": { - "title": "OpenID Connect Provider", - "type": "object", - "required": [ - "id", - "issuer", - "title" - ], - "properties": { - "id": { - "type": "string", - "description": "A per-backend **unique** identifier for the OpenID Connect Provider to be as prefix for the Bearer token.", - "pattern": "[\\d\\w]{1,20}" - }, - "issuer": { - "type": "string", - "format": "uri", - "description": "The [issuer location](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig) (also referred to as 'authority' in some client libraries) is the URL of the OpenID Connect provider, which conforms to a set of rules:\n1. After appending `/.well-known/openid-configuration` to the URL, a [HTTP/1.1 GET request](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest) to the concatenated URL MUST return a [OpenID Connect Discovery Configuration Response](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). The response provides all information required to authenticate using OpenID Connect.\n2. The URL MUST NOT contain a terminating forward slash `/`.", - "example": "https://accounts.google.com" - }, - "scopes": { - "type": "array", - "description": "A list of OpenID Connect scopes that the client MUST at least include when requesting authorization. Clients MAY add additional scopes such as the `offline_access` scope to retrieve a refresh token.\nIf scopes are specified, the list MUST at least contain the `openid` scope.", - "items": { - "type": "string" - } - }, - "title": { - "type": "string", - "description": "The name that is publicly shown in clients for this OpenID Connect provider." - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "A description that explains how the authentication procedure works.\n\nIt should make clear how to register and get credentials. This should\ninclude instruction on setting up `client_id`, `client_secret` and `redirect_uri`.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich\ntext representation." - }, - "default_clients": { - "title": "Default OpenID Connect Clients", - "type": "array", - "description": "List of default OpenID Connect clients that can be used by an openEO client\nfor OpenID Connect based authentication.\n\nA default OpenID Connect client is managed by the back-end implementer.\nIt MUST be configured to be usable without a client secret,\nwhich limits its applicability to OpenID Connect grant types like\n\"Authorization Code Grant with PKCE\" and \"Device Authorization Grant with PKCE\"\n\nA default OpenID Connect client is provided without availability guarantees.\nThe back-end implementer CAN revoke, reset or update it any time.\nAs such, openEO clients SHOULD NOT store or cache default OpenID Connect client information\nfor long term usage.\nA default OpenID Connect client is intended to simplify authentication for novice users.\nFor production use cases, it is RECOMMENDED to set up a dedicated OpenID Connect client.", - "uniqueItems": true, - "items": { - "title": "Default OpenID Connect Client", - "type": "object", - "required": [ - "id", - "grant_types" - ], - "properties": { - "id": { - "type": "string", - "description": "The OpenID Connect Client ID to be used in the authentication procedure." - }, - "grant_types": { - "type": "array", - "description": "List of authorization grant types (flows) supported by the OpenID Connect client.\nA grant type descriptor consist of a OAuth 2.0 grant type,\nwith an additional `+pkce` suffix when the grant type should be used with\nthe PKCE extension as defined in [RFC 7636](https://www.rfc-editor.org/rfc/rfc7636.html).\n\nAllowed values:\n- `implicit`: Implicit Grant as specified in [RFC 6749, sec. 1.3.2](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.3.2)\n- `authorization_code` / `authorization_code+pkce`: Authorization Code Grant as specified in [RFC 6749, sec. 1.3.1](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.3.1), with or without PKCE extension.\n- `urn:ietf:params:oauth:grant-type:device_code` / `urn:ietf:params:oauth:grant-type:device_code+pkce`: Device Authorization Grant (aka Device Code Flow) as specified in [RFC 8628](https://www.rfc-editor.org/rfc/rfc8628.html), with or without PKCE extension. Note that the combination of this grant with the PKCE extension is *not standardized* yet.\n- `refresh_token`: Refresh Token as specified in [RFC 6749, sec. 1.5](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.5)", - "minItems": 1, - "uniqueItems": true, - "items": { - "type": "string", - "enum": [ - "implicit", - "authorization_code", - "authorization_code+pkce", - "urn:ietf:params:oauth:grant-type:device_code", - "urn:ietf:params:oauth:grant-type:device_code+pkce", - "refresh_token" - ] - } - }, - "redirect_urls": { - "type": "array", - "description": "List of redirect URLs that are whitelisted by the OpenID Connect client.\nRedirect URLs MUST be provided when the OpenID Connect client supports\nthe Implicit Grant or the Authorization Code Grant (with or without PKCE extension).", - "uniqueItems": true, - "items": { - "type": "string", - "format": "uri" - } - } - } - } - }, - "links": { - "type": "array", - "description": "Links related to this provider, for example a\nhelp page or a page to register a new user account.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - } - } - } - } - } - }, - "example": { - "providers": [ - { - "id": "egi", - "issuer": "https://aai.egi.eu/oidc", - "title": "EGI (default)", - "description": "Login with your academic account.", - "scopes": [ - "openid", - "profile", - "email" - ], - "default_clients": [ - { - "id": "KStcUzD5AIUA", - "grant_types": [ - "implicit", - "authorization_code+pkce", - "urn:ietf:params:oauth:grant-type:device_code+pkce", - "refresh_token" - ], - "redirect_urls": [ - "https://editor.openeo.org/" - ] - } - ] - }, - { - "id": "google", - "issuer": "https://accounts.google.com", - "title": "Google", - "description": "Login with your Google Account.", - "scopes": [ - "openid", - "profile", - "email", - "earthengine" - ] - }, - { - "id": "ms", - "issuer": "https://login.microsoftonline.com/example-tenant/v2.0", - "title": "Microsoft", - "description": "Login with your Microsoft or Skype Account.", - "scopes": [] - } - ] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/credentials/basic": { - "get": { - "summary": "HTTP Basic authentication", - "operationId": "authenticate-basic", - "description": "Checks the credentials provided through [HTTP Basic Authentication according to RFC 7617](https://www.rfc-editor.org/rfc/rfc7617.html) and returns an access token for valid credentials.\n\nThe credentials (username and password) MUST be sent in the HTTP header `Authorization` with type `Basic` and the Base64 encoded string consisting of username and password separated by a double colon `:`. The header would look as follows for username `user` and password `pw`: `Authorization: Basic dXNlcjpwdw==`.\n\nThe access token has to be used in the Bearer token for authorization in subsequent API calls (see also the information about Bearer tokens in this document). The access token returned by this request MUST NOT be provided with `basic//` prefix, but the Bearer Token sent in subsequent API calls to protected endpoints MUST be prefixed with `basic//`. The header in subsequent API calls would look as follows: `Authorization: Bearer basic//TOKEN` (replace `TOKEN` with the actual access token).\n\nIt is RECOMMENDED to implement this authentication method for non-public services only.", - "tags": [ - "Account Management" - ], - "security": [ - { - "Basic": [] - } - ], - "responses": { - "200": { - "description": "Credentials are correct and authentication succeeded.", - "content": { - "application/json": { - "schema": { - "title": "HTTP Basic Access Token", - "type": "object", - "required": [ - "access_token" - ], - "properties": { - "access_token": { - "description": "The access token (without `basic//` prefix) to be used in the Bearer token for authorization in subsequent API calls.", - "type": "string", - "example": "b34ba2bdf9ac9ee1" - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/validation": { - "post": { - "summary": "Validate a user-defined process (graph)", - "operationId": "validate-custom-process", - "description": "Validates a user-defined process without executing it. A user-defined process is\nconsidered valid unless the `errors` array in the response contains at\nleast one error.\n\nChecks whether the process graph is schematically correct and the\nprocesses are supported by the back-end. It MUST also check the\narguments against the schema, but checking whether the arguments are\nadequate in the context of data is OPTIONAL. For example, a non-existing\nband name may get rejected only by a few back-ends.\nThe validation MUST NOT throw an error for unresolvable process parameters.\n\nBack-ends MUST validate the process graph. Validating the corresponding\nmetadata is OPTIONAL.\n\nErrors that usually occur during processing MAY NOT get reported, e.g.\nif a referenced file is accessible at the time of execution.\n\nBack-ends can either report all errors at once or stop the validation\nonce they found the first error. \n\nPlease note that a validation always returns with HTTP status code 200.\nError codes in the 4xx and 5xx ranges MUST be returned only when the\ngeneral validation request is invalid (e.g. server is busy or properties\nin the request body are missing), but never if an error was found during\nvalidation of the user-defined process (e.g. an unsupported process).", - "tags": [ - "Data Processing", - "User-Defined Processes" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Returns the validation result as a list of errors. An empty list indicates a successful validation.", - "content": { - "application/json": { - "schema": { - "title": "Validation Result", - "type": "object", - "required": [ - "errors" - ], - "properties": { - "errors": { - "description": "A list of validation errors.", - "type": "array", - "items": { - "$ref": "#/components/schemas/error" - } - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "examples": { - "evi_user_defined_process": { - "$ref": "#/components/examples/evi_user_defined_process" - } - } - } - }, - "description": "Specifies the user-defined process to be validated." - } - } - }, - "/result": { - "post": { - "summary": "Process and download data synchronously", - "operationId": "compute-result", - "description": "Executes a user-defined process directly (synchronously) and the result will be downloaded in the format specified in the process graph. This endpoint can be used to generate small previews or test user-defined processes before starting a batch job.\nTimeouts on either client- or server-side are to be expected for complex computations. Back-ends MAY send the openEO error `ProcessGraphComplexity` immediately if the computation is expected to time out. Otherwise requests MAY time-out after a certain amount of time by sending openEO error `RequestTimeout`.\nA header named `OpenEO-Costs` MAY be sent with all responses, which MUST include the costs for processing and downloading the data. Additionally, a link to a log file MAY be sent in the header.", - "tags": [ - "Data Processing" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Result data in the requested output format", - "headers": { - "Content-Type": { - "description": "The appropriate media (MIME) type for the requested output\nformat MUST be sent, if the response contains a single file.\n\nTo send multiple files at once it is RECOMMENDED to use the\n[`tar` file format](https://www.gnu.org/software/tar/manual/html_node/Standard.html)\n(media type: `application/x-tar`).\n\nTo mimic the results of batch jobs, it is RECOMMENDED that \n1. clients extract the tar file directly after receiving it so that users\n can directly work on the contained files *and*\n2. back-ends add STAC Items and/or Collections to the tar file\n so that users can make sense of the files.", - "schema": { - "type": "string" - } - }, - "OpenEO-Costs": { - "description": "MAY include the costs for processing and downloading the data.", - "schema": { - "$ref": "#/components/schemas/money" - } - }, - "Link": { - "description": "The header MAY indicate a link to a log file generated by the request. If provided, the link MUST be serialized according to [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288.html#section-3) and MUST use the relation type `monitor`. The link MUST follow the specifications for the links `GET /jobs/{job_id}/logs` and `GET /services/{service_id}/logs`, except that is MUST NOT accept any parameters (limit/offset). Therefore, the link MUST be accessible with HTTP GET, MUST be secured using a Bearer token and MUST follow the corresponding request body schema.", - "schema": { - "type": "string", - "pattern": "^<[^>]+>;\\s?rel=\"monitor\"", - "example": "; rel=\"monitor\"" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "description": "Specifies the job details, e.g. the user-defined process and billing details.", - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Synchronous Result Request", - "type": "object", - "required": [ - "process" - ], - "properties": { - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null_default" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - } - }, - "additionalProperties": { - "description": "You can add additional back-end specific properties here." - } - } - } - } - } - } - }, - "/process_graphs": { - "get": { - "summary": "List all user-defined processes", - "operationId": "list-custom-processes", - "description": "Lists all user-defined processes (process graphs) of the\nauthenticated user that are stored at the back-end.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting larger optional values from the objects in `processes`\n(e.g. the `exceptions`, `examples` and `links` properties).\nTo get the full metadata for a user-defined process clients MUST\nrequest `GET /process_graphs/{process_graph_id}`.", - "tags": [ - "User-Defined Processes", - "Process Discovery" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "JSON array with user-defined processes.", - "content": { - "application/json": { - "schema": { - "title": "User-Defined Processes", - "type": "object", - "required": [ - "processes", - "links" - ], - "properties": { - "processes": { - "description": "Array of user-defined processes", - "type": "array", - "items": { - "$ref": "#/components/schemas/user_defined_process_meta" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - }, - "example": { - "processes": [ - { - "id": "evi", - "summary": "Enhanced Vegetation Index", - "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", - "parameters": [ - { - "name": "red", - "description": "Value from the red band.", - "schema": { - "type": "number" - } - }, - { - "name": "blue", - "description": "Value from the blue band.", - "schema": { - "type": "number" - } - }, - { - "name": "nir", - "description": "Value from the near infrared band.", - "schema": { - "type": "number" - } - } - ], - "returns": { - "description": "Computed EVI.", - "schema": { - "type": "number" - } - } - }, - { - "id": "ndsi", - "summary": "Normalized-Difference Snow Index", - "parameters": [ - { - "name": "green", - "description": "Value from the Visible Green (0.53 - 0.61 micrometers) band.", - "schema": { - "type": "number" - } - }, - { - "name": "swir", - "description": "Value from the Short Wave Infrared (1.55 - 1.75 micrometers) band.", - "schema": { - "type": "number" - } - } - ], - "returns": { - "schema": { - "type": "number" - } - } - }, - { - "id": "my_custom_process" - } - ], - "links": [] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/process_graphs/{process_graph_id}": { - "parameters": [ - { - "name": "process_graph_id", - "in": "path", - "description": "Per-user unique identifier for a user-defined process.", - "required": true, - "schema": { - "$ref": "#/components/schemas/process_id" - } - } - ], - "get": { - "summary": "Full metadata for a user-defined process", - "operationId": "describe-custom-process", - "description": "Lists all information about a user-defined process, including its process graph.", - "tags": [ - "User-Defined Processes", - "Process Discovery" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "The user-defined process with process graph.", - "content": { - "application/json": { - "schema": { - "title": "User-Defined Process", - "description": "A user-defined process with processing instructions as process graph.", - "type": "object", - "required": [ - "process_graph" - ], - "allOf": [ - { - "$ref": "#/components/schemas/user_defined_process_meta" - } - ] - }, - "examples": { - "evi_user_defined_process": { - "$ref": "#/components/examples/evi_user_defined_process" - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "put": { - "summary": "Store a user-defined process", - "operationId": "store-custom-process", - "description": "Stores a provided user-defined process with process graph that can be\nreused in other processes.\n\nIf a process with the specified `process_graph_id` exists, the process\nis fully replaced. The id can't be changed for existing user-defined\nprocesses. The id MUST be unique across its namespace.\n\nPartially updating user-defined processes is not supported.\n\nTo simplify exchanging user-defined processes, the property `id` can be part of\nthe request body. If the values don't match, the value for `id` gets\nreplaced with the value from the `process_graph_id` parameter in the\npath.", - "tags": [ - "User-Defined Processes" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "The user-defined process has been stored successfully." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "description": "Specifies the process graph with its meta data.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "examples": { - "evi_user_defined_process": { - "$ref": "#/components/examples/evi_user_defined_process" - } - } - } - } - } - }, - "delete": { - "summary": "Delete a user-defined process", - "operationId": "delete-custom-process", - "description": "Deletes the data related to this user-defined process, including its process graph.\n\nDoes NOT delete jobs or services that reference this user-defined process.", - "tags": [ - "User-Defined Processes" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "The user-defined process has been successfully deleted" - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/service_types": { - "get": { - "summary": "Supported secondary web service protocols", - "operationId": "list-service-types", - "description": "Lists supported secondary web service protocols such as\n[OGC WMS](http://www.opengeospatial.org/standards/wms),\n[OGC WCS](http://www.opengeospatial.org/standards/wcs),\n[OGC API - Features](https://www.ogc.org/standards/ogcapi-features)\nor [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).\nThe response is an object of all available secondary web service protocols\nwith their supported configuration settings and expected process parameters.\n\n* The configuration settings for the service SHOULD be defined upon\n creation of a service and the service will be set up accordingly.\n* The process parameters SHOULD be referenced (with a `from_parameter`\n reference) in the user-defined process that is used to compute web service\n results.\n The appropriate arguments MUST be provided to the user-defined process,\n usually at runtime from the context of the web service,\n For example, a map service such as a WMS would\n need to inject the spatial extent into the user-defined process so that the\n back-end can compute the corresponding tile correctly.\n\nTo improve interoperability between back-ends common names for the\nservices SHOULD be used, e.g. the abbreviations used in the official\n[OGC Schema Repository](http://schemas.opengis.net/) for the respective\nservices.\n\nService names MUST be accepted in a *case insensitive* manner throughout the API.", - "tags": [ - "Capabilities", - "Secondary Services" - ], - "security": [ - {}, - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "An object with a map containing all service names as keys and an object that defines supported configuration settings and process parameters.", - "content": { - "application/json": { - "schema": { - "title": "Service Types", - "type": "object", - "description": "Map of supported secondary web services.", - "additionalProperties": { - "x-additionalPropertiesName": "Service Name", - "title": "Service Type", - "type": "object", - "required": [ - "configuration", - "process_parameters" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/object_title" - }, - "description": { - "$ref": "#/components/schemas/description" - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "configuration": { - "title": "Service Configuration", - "description": "Map of supported configuration settings made available to the creator of the service.", - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/resource_parameter" - } - }, - "process_parameters": { - "title": "Process Parameters", - "description": "List of parameters made available to user-defined processes.", - "type": "array", - "items": { - "$ref": "#/components/schemas/process_parameter" - } - }, - "links": { - "description": "Links related to this service type, e.g. more\ninformation about the configuration settings and process parameters.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - } - } - } - } - }, - "example": { - "WMS": { - "title": "OGC Web Map Service", - "configuration": { - "version": { - "type": "string", - "description": "The WMS version offered to consumers of the service.", - "default": "1.3.0", - "enum": [ - "1.1.1", - "1.3.0" - ] - } - }, - "process_parameters": [ - { - "name": "layer", - "description": "The layer name.", - "schema": { - "type": "string" - }, - "default": "roads" - }, - { - "name": "spatial_extent", - "description": "A bounding box in WGS84.", - "schema": { - "type": "object", - "required": [ - "west", - "south", - "east", - "north" - ], - "properties": { - "west": { - "description": "West (lower left corner, coordinate axis 1).", - "type": "number" - }, - "south": { - "description": "South (lower left corner, coordinate axis 2).", - "type": "number" - }, - "east": { - "description": "East (upper right corner, coordinate axis 1).", - "type": "number" - }, - "north": { - "description": "North (upper right corner, coordinate axis 2).", - "type": "number" - } - } - } - } - ], - "links": [ - { - "href": "https://www.opengeospatial.org/standards/wms", - "rel": "about", - "title": "OGC Web Map Service Standard" - } - ] - }, - "OGCAPI-FEATURES": { - "title": "OGC API - Features", - "description": "Exposes a OGC API - Features in version 1.0 of the specification (successor of OGC WFS 3.0).", - "configuration": { - "title": { - "type": "string", - "description": "The title for the OGC API - Features landing page" - }, - "description": { - "type": "string", - "description": "The description for the OGC API - Features landing page" - }, - "conformsTo": { - "type": "array", - "description": "The OGC API - Features conformance classes to enable for this service.\n\n`http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core` is always enabled.", - "items": { - "type": "string", - "enum": [ - "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30", - "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/html", - "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson", - "http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs" - ] - } - } - }, - "process_parameters": [], - "links": [ - { - "href": "https://www.opengeospatial.org/standards/wfs", - "rel": "about", - "title": "OGC Web Feature Service Standard" - } - ] - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/services": { - "get": { - "summary": "List all web services", - "operationId": "list-services", - "description": "Lists all secondary web services submitted by a user.\n\nIt is **strongly RECOMMENDED** to keep the response size small by omitting\nall optional non-scalar values (i.e. arrays and objects) from objects in `services`\n(i.e. the `process`, `configuration` and `attributes` properties).\nTo get the full metadata for a secondary web service clients MUST\nrequest `GET /services/{service_id}`.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Array of secondary web service descriptions", - "content": { - "application/json": { - "schema": { - "title": "Secondary Web Services", - "type": "object", - "required": [ - "services", - "links" - ], - "properties": { - "services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/service" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "post": { - "summary": "Publish a new service", - "operationId": "create-service", - "description": "Creates a new secondary web service such as a\n[OGC WMS](http://www.opengeospatial.org/standards/wms),\n[OGC WCS](http://www.opengeospatial.org/standards/wcs),\n[OGC API - Features](https://www.ogc.org/standards/ogcapi-features)\nor [XYZ tiles](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).\n\nThe secondary web service SHOULD process the underlying\ndata on demand, based on process parameters provided to the\nuser-defined process (through `from_parameter` references) at run-time,\nfor example for the spatial/temporal extent, resolution, etc.\nThe available process parameters are specified per\nservice type at `GET /service_types`.\n\n**Note:** Costs incurred by shared secondary web services are usually\npaid by the owner, but this depends on the service type and whether it\nsupports charging fees or not.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "201": { - "description": "The service has been created successfully.", - "headers": { - "Location": { - "required": true, - "schema": { - "description": "Absolute URL to the newly created service.\n\nThe URL points to the metadata endpoint\n`GET /services/{service_id}` with the `{service_id}` being the\nunique identifier (ID) of the created service.\nMUST NOT point to the actual instance (e.g. WMTS base URL) of\nthe service. The URL to the instance is made available by the\nmetadata endpoint in the property `url`.", - "format": "uri", - "type": "string", - "example": "https://openeo.example/api/v1/services/123" - } - }, - "OpenEO-Identifier": { - "required": true, - "schema": { - "$ref": "#/components/schemas/service_id" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Store Secondary Web Service Request", - "type": "object", - "required": [ - "type", - "process" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "type": { - "$ref": "#/components/schemas/service_type" - }, - "enabled": { - "allOf": [ - { - "$ref": "#/components/schemas/service_enabled" - }, - { - "default": true - } - ] - }, - "configuration": { - "$ref": "#/components/schemas/service_configuration" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null_default" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - } - }, - "additionalProperties": { - "description": "You can add additional back-end specific properties here." - } - } - } - }, - "description": "The base data for the secondary web service to create" - } - } - }, - "/services/{service_id}": { - "parameters": [ - { - "$ref": "#/components/parameters/service_id" - } - ], - "patch": { - "summary": "Modify a service", - "operationId": "update-service", - "description": "Modifies an existing secondary web service at the back-end,\nbut maintain the identifier. Changes can be grouped in a single request.\n\nUser have to create a new service to change the service type.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "Changes to the service were applied successfully." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Update Secondary Web Service Request", - "type": "object", - "properties": { - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "enabled": { - "$ref": "#/components/schemas/service_enabled" - }, - "configuration": { - "$ref": "#/components/schemas/service_configuration" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null" - }, - "budget": { - "$ref": "#/components/schemas/budget_update" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_update" - } - } - } - } - }, - "description": "The data to change for the specified secondary web service." - } - }, - "get": { - "summary": "Full metadata for a service", - "operationId": "describe-service", - "description": "Lists all information about a secondary web service.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Details of the created service", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "process", - "configuration", - "attributes" - ], - "allOf": [ - { - "$ref": "#/components/schemas/service" - } - ] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "delete": { - "summary": "Delete a service", - "operationId": "delete-service", - "description": "Deletes all data related to this secondary web service. Computations are stopped, computed results are deleted and access to this is not possible any more. This service won't generate additional costs.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "The service has been successfully deleted." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/services/{service_id}/logs": { - "get": { - "summary": "Logs for a secondary service", - "operationId": "debug-service", - "description": "Lists log entries for the secondary service, usually for debugging purposes.\nBack-ends can log any information that may be relevant for a user. Users can log information during data processing using respective processes such as `inspect`.\nIf requested consecutively while the secondary service is enabled, it is RECOMMENDED that clients use the offset parameter to get only the entries they have not received yet.\nWhile pagination itself is OPTIONAL, the `offset` parameter is REQUIRED to be implemented by back-ends.", - "tags": [ - "Secondary Services" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/service_id" - }, - { - "$ref": "#/components/parameters/log_offset" - }, - { - "$ref": "#/components/parameters/log_level" - }, - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/logs" - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/jobs": { - "get": { - "summary": "List all batch jobs", - "operationId": "list-jobs", - "description": "Lists all batch jobs submitted by a user.\n\nIt is **strongly RECOMMENDED** to keep the response size small by\nomitting all optional non-scalar values (i.e. arrays and objects) from\nobjects in `jobs` (i.e. the `process` property).\nTo get the full metadata for a job clients MUST request `GET /jobs/{job_id}`.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Array of job descriptions", - "content": { - "application/json": { - "schema": { - "title": "Batch Jobs", - "type": "object", - "required": [ - "jobs", - "links" - ], - "properties": { - "jobs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/batch_job" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "post": { - "summary": "Create a new batch job", - "operationId": "create-job", - "description": "Creates a new batch processing task (job) from one or more (chained)\nprocesses at the back-end.\n\nProcessing the data doesn't start yet. The job status gets initialized\nas `created` by default.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "201": { - "description": "The batch job has been created successfully.", - "headers": { - "Location": { - "required": true, - "schema": { - "description": "Absolute URL to the newly created batch job.\n\nThe URL points to the metadata endpoint\n`GET /jobs/{job_id}` with the `{job_id}` being the\nunique identifier (ID) of the created batch job.", - "format": "uri", - "type": "string", - "example": "https://openeo.example/api/v1/jobs/123" - } - }, - "OpenEO-Identifier": { - "required": true, - "schema": { - "$ref": "#/components/schemas/job_id" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Store Batch Job Request", - "type": "object", - "required": [ - "process" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null_default" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - } - }, - "additionalProperties": { - "description": "You can add additional back-end specific properties here." - } - } - } - }, - "description": "Specifies the job details, e.g. the user-defined process and billing details." - } - } - }, - "/jobs/{job_id}": { - "parameters": [ - { - "$ref": "#/components/parameters/job_id" - } - ], - "patch": { - "summary": "Modify a batch job", - "operationId": "update-job", - "description": "Modifies an existing job at the back-end, but maintains the identifier.\nChanges can be grouped in a single request.\n\nThe job status does not change.\n\nJobs can only be modified when the job is not queued and not running.\nOtherwise, requests to this endpoint MUST be rejected with openEO error\n`JobLocked`.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "Changes to the job applied successfully." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Update Batch Job Request", - "type": "object", - "properties": { - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan_null" - }, - "budget": { - "$ref": "#/components/schemas/budget_update" - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_update" - } - } - } - } - }, - "description": "Specifies the job details to update." - } - }, - "get": { - "summary": "Full metadata for a batch job", - "operationId": "describe-job", - "description": "Lists all information about a submitted batch job.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Full job information.", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "process" - ], - "allOf": [ - { - "$ref": "#/components/schemas/batch_job" - } - ] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "delete": { - "summary": "Delete a batch job", - "operationId": "delete-job", - "description": "Deletes all data related to this job. Computations are stopped and computed results are deleted. This job won't generate additional costs for processing.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "The job has been successfully deleted." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/jobs/{job_id}/estimate": { - "get": { - "summary": "Get an estimate for a batch job", - "operationId": "estimate-job", - "description": "Calculates an estimate for a batch job. Back-ends can decide to either calculate the duration, the costs, the size or a combination of them.\nBack-end providers MAY specify an expiry time for the estimate. Starting to process data afterwards MAY be charged at a higher cost. Costs do often not include download costs. Whether download costs are included or not can be indicated explicitly with the `downloads_included` flag.\nThe estimate SHOULD be the upper limit of the costs, but back-end are free to use the field according to their terms of service.\nFor some batch jobs it is not (easily) possible to estimate the costs reliably, e.g. if a UDF or ML model is part of the process. In this case, the server SHOULD return a `EstimateComplexity` error with HTTP status code 500.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/job_id" - } - ], - "responses": { - "200": { - "description": "The estimated costs with regard to money, processing time and storage capacity. At least one of `costs`, `duration` or `size` MUST be provided.", - "content": { - "application/json": { - "schema": { - "title": "Batch Job Estimate", - "type": "object", - "anyOf": [ - { - "required": [ - "costs" - ] - }, - { - "required": [ - "duration" - ] - }, - { - "required": [ - "size" - ] - } - ], - "properties": { - "costs": { - "$ref": "#/components/schemas/money" - }, - "duration": { - "type": "string", - "description": "Estimated duration for the operation. Duration MUST be specified as a ISO 8601 duration.", - "example": "P1Y2M10DT2H30M" - }, - "size": { - "type": "integer", - "description": "Estimated required storage capacity, i.e. the size of the generated files. Size MUST be specified in bytes.", - "example": 157286400 - }, - "downloads_included": { - "type": "integer", - "nullable": true, - "description": "Specifies how many full downloads of the processed data are included in the estimate. Set to `null` for unlimited downloads, which is also the default value.", - "example": 5, - "default": null - }, - "expires": { - "type": "string", - "format": "date-time", - "description": "Time until which the estimate is valid, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2020-11-01T00:00:00Z" - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/jobs/{job_id}/logs": { - "get": { - "summary": "Logs for a batch job", - "operationId": "debug-job", - "description": "Lists log entries for the batch job, usually for debugging purposes.\n\nBack-ends can log any information that may be relevant for a user\nat any stage (status) of the batch job.\nUsers can log information during data processing using respective\nprocesses such as `inspect`.\n\nIf requested consecutively, it is RECOMMENDED that clients use the offset\nparameter to get only the entries they have not received yet.\n\nWhile pagination itself is OPTIONAL, the `offset` parameter is REQUIRED\nto be implemented by back-ends.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/job_id" - }, - { - "$ref": "#/components/parameters/log_offset" - }, - { - "$ref": "#/components/parameters/log_level" - }, - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/logs" - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/jobs/{job_id}/results": { - "parameters": [ - { - "$ref": "#/components/parameters/job_id" - } - ], - "get": { - "summary": "List batch job results", - "operationId": "list-results", - "description": "Lists signed URLs pointing to the processed files, usually after the batch job\nhas finished. Back-ends may also point to intermediate results after the\njob has stopped due to an error or if the `partial` parameter has been set.\n\nThe response includes additional metadata. It is a valid\n[STAC Item](https://github.com/radiantearth/stac-spec/tree/v1.0.0/item-spec)\n(if it has spatial and temporal references included) or a valid\n[STAC Collection](https://github.com/radiantearth/stac-spec/tree/v1.0.0/collection-spec)\n(supported since openEO API version 1.1.0).\nThe assets to download are in both cases available in the property `assets`\nand have the same structure. All additional metadata is not strictly required\nto download the files, but are helpful for users to understand the data.\n\nSTAC Collections can either (1) add all assets as collection-level assets or\n(2) link to STAC Catalogs and STAC Items with signed URLs, which will provide a full\nSTAC catalog structure a client has to go through. Option 2 is overall the better \narchitectural choice and allows a fine-grained description of the processed data,\nbut it is not compliant with previous versions of the openEO API.\n**To maintain backward compatibility, it is REQUIRED to still copy\nall assets in the STAC catalog structure into the collection-level assets.**\nThis requirement is planned to be removed in openEO API version 2.0.0.\nA client can enforce that the server returns a GeoJSON through content negotiation\nwith the media type `application/geo+json`, but the results may not contain very\nmeaningful metadata aside from the assets.\n\nClients are RECOMMENDED to store this response and all potential sub-catalogs\nand items with the assets so that the downloaded data is then a self-contained\nSTAC catalog user could publish easily with all the data and metadata.\n\nURL signing is a way to protect files from unauthorized access with a\nkey in the URL instead of HTTP header based authorization. The URL\nsigning key is similar to a password and its inclusion in the URL allows\nto download files using simple GET requests supported by a wide range of\nprograms, e.g. web browsers or download managers. Back-ends are\nresponsible to generate the URL signing keys and to manage their\nappropriate expiration. The back-end MAY indicate an expiration time by\nsetting the `expires` property in the reponse. Requesting this endpoint\nSHOULD always return non-expired URLs. Signed URLs that were generated\nfor a previous request and already expired SHOULD NOT be reused,\nbut regenerated with new expiration time.\nSigned URLs that expired MAY return the openEO error `ResultLinkExpired`.\n\nIt is **strongly recommended** to add a link with relation type `canonical`\nto the STAC Item or STAC Collection (see the `links` property for details).\n\nIf processing has not finished yet and the `partial` parameter is not set to `true`\nrequests to this endpoint MUST be rejected with openEO error `JobNotFinished`.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "name": "partial", - "description": "If set to `true`, the results endpoint returns incomplete results while still running.\nEnabling this parameter requires to indicate the status of the batch job in the STAC metadata by setting the `openeo:status`.", - "in": "query", - "allowEmptyValue": true, - "schema": { - "type": "boolean", - "default": false - } - } - ], - "responses": { - "200": { - "description": "Valid download links have been returned. The download links doesn't necessarily need to be located under the API base url.", - "headers": { - "OpenEO-Costs": { - "description": "Specifies the costs for fully downloading the data **once**, i.e. this header MAY change in subsequent calls. It MUST be set to `0` if the requester is the owner of the job and still has free downloads included in his processing charges estimated by `GET /jobs/{job_id}/estimate`. If a requester other than the owner is requesting the data of a shared job this header indicates the costs for the requester.", - "schema": { - "$ref": "#/components/schemas/money" - } - } - }, - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/batch_job_result" - }, - { - "title": "Batch Job Results Response as STAC Collection", - "type": "object", - "required": [ - "assets" - ], - "properties": { - "openeo:status": { - "$ref": "#/components/schemas/result_status" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/collection" - } - ], - "example": { - "stac_version": "1.0.0", - "id": "a3cca2b2aa1e3b5b", - "title": "NDVI based on Sentinel 2", - "description": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2", - "license": "Apache-2.0", - "providers": [ - { - "name": "Example Cloud Corp.", - "description": "No further processing applied.", - "roles": [ - "producer", - "licensor", - "host" - ], - "url": "https://cloud.example" - } - ], - "extent": { - "temporal": { - "interval": [ - [ - "2019-08-24T14:15:22Z", - "2019-08-24T14:15:22Z" - ] - ] - }, - "spatial": { - "bbox": [ - [ - -180, - -90, - 180, - 90 - ] - ] - } - }, - "assets": { - "preview.png": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/preview.png", - "type": "image/png", - "title": "Thumbnail", - "roles": [ - "thumbnail" - ] - }, - "process.json": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/process.json", - "type": "application/json", - "title": "Original Process", - "roles": [ - "process", - "reproduction" - ] - }, - "1.tif": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/1.tif", - "type": "image/tiff; application=geotiff", - "roles": [ - "data" - ] - }, - "2.tif": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/2.tif", - "type": "image/tiff; application=geotiff", - "roles": [ - "data" - ] - }, - "inspire.xml": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/inspire.xml", - "type": "application/xml", - "title": "INSPIRE metadata", - "description": "INSPIRE compliant XML metadata", - "roles": [ - "metadata" - ] - } - }, - "links": [ - { - "rel": "canonical", - "type": "application/json", - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/collection.json" - }, - { - "rel": "item", - "type": "application/geo+json", - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item_1.json" - }, - { - "rel": "item", - "type": "application/geo+json", - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item_2.json" - } - ] - } - } - ] - } - }, - "application/geo+json": { - "schema": { - "$ref": "#/components/schemas/batch_job_result" - } - } - } - }, - "424": { - "description": "The request can't be fulfilled as the batch job failed. This request will deliver the last error message that was produced by the batch job.\n\nThis HTTP code MUST be sent only when the job `status` is `error`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/log_entry" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "post": { - "summary": "Start processing a batch job", - "operationId": "start-job", - "description": "Adds a batch job to the processing queue to compute the results.\n\nThe result will be stored in the format specified in the process.\nTo specify the format use a process such as `save_result`.\n\nThe job status is set to `queued`, if processing doesn't start\ninstantly. The same applies if the job status is `canceled`, `finished`,\nor `error`, which restarts the job and discards previous results if the\nback-end doesn't reject the request with an error.\nClients SHOULD warn users and ask for confirmation if results may get\ndiscarded.\n\n* Once the processing starts the status is set to `running`.\n* Once the data is available to download the status is set to\n`finished`.\n* Whenever an error occurs during processing, the status MUST be set to\n`error`.\n\nThis endpoint has no effect if the job status is already `queued` or\n`running`. In particular, it doesn't restart a running job. To restart\na queued or running job, processing MUST have been canceled before.\n\nBack-ends SHOULD reject queueing jobs with openEO error `PaymentRequired`,\nif the back-end is able to detect that the budget is too low to fully\nprocess the request. Alternatively, back-ends MAY provide partial results\nonce reaching the budget. If none of the alternatives is feasible, the\nresults are discarded. Thus, client SHOULD warn users that reaching the\nbudget may lead to partial or no results at all.", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "202": { - "description": "The creation of the resource has been queued successfully." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "delete": { - "summary": "Cancel processing a batch job", - "operationId": "stop-job", - "description": "Cancels all related computations for this job at the back-end. It will\nstop generating additional costs for processing.\n\nA subset of processed results may be available for downloading depending\non the state of the job at the time it was canceled.\n\nResults MUST NOT be deleted until the job processing is started again or\nthe job is completely deleted through a request to\n`DELETE /jobs/{job_id}`.\n\nThis endpoint only has an effect if the job status is `queued` or\n`running`.\n\nThe job status is set to `canceled` if the status was `running`\nbeforehand and partial or preliminary results are available to be\ndownloaded. Otherwise the status is set to `created`. ", - "tags": [ - "Data Processing", - "Batch Jobs" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "Processing the job has been successfully canceled." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/files": { - "get": { - "summary": "List all files in the workspace", - "operationId": "list-files", - "description": "Lists all user-uploaded files that are stored at the back-end.", - "tags": [ - "File Storage" - ], - "security": [ - { - "Bearer": [] - } - ], - "parameters": [ - { - "$ref": "#/components/parameters/pagination_limit" - } - ], - "responses": { - "200": { - "description": "Flattened file tree with path relative to the user's root directory and some basic properties such as the file size and the timestamp of the last modification. All properties except the name are optional. Folders MUST NOT be listed separately so each element in the list MUST be a downloadable file.", - "content": { - "application/json": { - "schema": { - "title": "Workspace Files", - "type": "object", - "required": [ - "files", - "links" - ], - "properties": { - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/file" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - }, - "example": { - "files": [ - { - "path": "test.txt", - "size": 182, - "modified": "2015-10-20T17:22:10Z" - }, - { - "path": "test.tif", - "size": 183142, - "modified": "2017-01-01T09:36:18Z" - }, - { - "path": "Sentinel2/S2A_MSIL1C_20170819T082011_N0205_R121_T34KGD_20170819T084427.zip", - "size": 4183353142, - "modified": "2018-01-03T10:55:29Z" - } - ], - "links": [] - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/files/{path}": { - "parameters": [ - { - "name": "path", - "in": "path", - "description": "Path of the file, relative to the user's root directory. MAY include folders, but MUST not include relative references such as `.` and `..`.\n\nFolder and file names in the path MUST be url-encoded. The path separator `/` and the file extension separator `.` MUST NOT be url-encoded.\n\nThe URL-encoding may be shown incorrectly in rendered versions due to [OpenAPI 3 not supporting path parameters which contain slashes](https://github.com/OAI/OpenAPI-Specification/issues/892). This may also lead to OpenAPI validators not validating paths containing folders correctly.", - "required": true, - "schema": { - "type": "string" - }, - "examples": { - "normal": { - "description": "A path without special chars. It describes a file `europe.geojson` in a folder called `borders`.", - "value": "borders/europe.geojson" - }, - "specialchars": { - "description": "A path with special chars. It describes a file `münster.shp` in folders called `europe` and `österreich`.", - "value": "europe/%C3%B6sterreich/m%C3%BCnster.shp" - } - } - } - ], - "get": { - "summary": "Download a file from the workspace", - "operationId": "download-file", - "description": "Offers a file from the user workspace for download. The file is identified by its path relative to the user's root directory.\nIf a folder is specified as path a `FileOperationUnsupported` error MUST be sent as response.", - "tags": [ - "File Storage" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "A file from the workspace.", - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - }, - "put": { - "summary": "Upload a file to the workspace", - "operationId": "upload-file", - "description": "Uploads a new file to the given path or updates an existing file if a file at the path exists.\n\nFolders are created once required by a file upload. Empty folders can't be created.", - "tags": [ - "File Storage" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "The file has been uploaded successfully.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/file" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - }, - "requestBody": { - "required": true, - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - } - }, - "delete": { - "summary": "Delete a file from the workspace", - "operationId": "delete-file", - "description": "Deletes an existing user-uploaded file specified by its path. Resulting empty folders MUST be deleted automatically.\n\nBack-ends MAY support deleting folders including its files and sub-folders. If not supported by the back-end a `FileOperationUnsupported` error MUST be sent as response.", - "tags": [ - "File Storage" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "204": { - "description": "The file has been successfully deleted at the back-end." - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - }, - "/me": { - "get": { - "summary": "Information about the authenticated user", - "operationId": "describe-account", - "description": "Lists information about the authenticated user, e.g. the user id.\nThe endpoint MAY return the disk quota available to the user. The endpoint MAY also return links related to user management and the user profile, e.g. where payments are handled or the user profile could be edited.\nFor back-ends that involve accounting, this service MAY also return the currently available money or credits in the currency the back-end is working with.\nThis endpoint MAY be extended to fulfil the specification of the [OpenID Connect UserInfo Endpoint](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo).", - "tags": [ - "Account Management" - ], - "security": [ - { - "Bearer": [] - } - ], - "responses": { - "200": { - "description": "Information about the logged in user.", - "content": { - "application/json": { - "schema": { - "title": "User Data", - "description": "Holds user information. If no budget or storage limit applies to the user account the corresponding properties MUST be set to null.", - "type": "object", - "required": [ - "user_id" - ], - "properties": { - "user_id": { - "type": "string", - "description": "A unique user identifier specific to the back-end, which could either be chosen by a user or is automatically generated by the back-end during the registration process at the back-end.\nIt is meant to be used as an identifier in URIs (e.g. for sharing purposes), which is primarily used in machine-to-machine communication. Preferrably use the human-readable property `name` to display the user's name in user interfaces instead of the user identifier.", - "pattern": "^[\\w\\-\\.~]+$", - "example": "john_doe" - }, - "name": { - "type": "string", - "description": "The user name, a human-friendly displayable name. Could be the user's real name or a nickname." - }, - "default_plan": { - "type": "string", - "description": "Name of the single plan the user is currently subscribed to if any.", - "example": "free" - }, - "storage": { - "title": "User Storage", - "description": "Information about the storage space available to the user.", - "type": "object", - "nullable": true, - "required": [ - "free", - "quota" - ], - "properties": { - "free": { - "type": "integer", - "description": "Free storage space in bytes, which is still available to the user. Effectively, this is the disk quota minus the used space by the user, e.g. user-uploaded files and job results.", - "example": 536870912 - }, - "quota": { - "type": "integer", - "description": "Maximum storage space (disk quota) in bytes available to the user.", - "example": 1073741824 - } - } - }, - "budget": { - "type": "number", - "nullable": true, - "description": "The remaining budget a user has available.\nThe value MUST be specified in the currency of the back-end.\nThe value SHOULD be set to `null` if no explicit limit applies." - }, - "links": { - "description": "Links related to the user profile, e.g. where payments\nare handled or the user profile could be edited.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `payment`: A page where users can recharge their user account with money or credits.\n\n2. `edit-form`: Points to a page where the user can edit his user profile.\n\n3. `alternate`: Any other representation of these (and potentially additional)\nuser information, e.g. the (public) user profile page.\nIt is RECOMMENDED to add descriptive titles for a better user experience.\n\n4. `related`: Any other user-specific links to be shown in clients,\ne.g. to user-specific settings, invoices, etc. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "href": "https://openeo.example/john_doe/payment/", - "rel": "payment" - }, - { - "href": "https://openeo.example/john_doe/edit/", - "rel": "edit-form" - }, - { - "href": "https://openeo.example/john_doe/", - "rel": "alternate", - "type": "text/html", - "title": "User profile" - }, - { - "href": "https://openeo.example/john_doe.vcf", - "rel": "alternate", - "type": "text/vcard", - "title": "vCard of John Doe" - }, - { - "href": "https://openeo.example/john_doe/invoices", - "rel": "related", - "type": "text/html", - "title": "Invoices" - } - ] - } - } - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/client_error_auth" - }, - "5XX": { - "$ref": "#/components/responses/server_error" - } - } - } - } - }, - "components": { - "schemas": { - "conformsTo": { - "description": "Lists all conformance classes specified in various standards that the\nimplementation conforms to. Conformance classes are commonly used in\nall OGC APIs and the STAC API specification.\n\nThe general openEO conformance class is `https://api.openeo.org/1.2.0`.\nSee the individual openEO API extensions for their conformance classes.\n\nThis property is REQUIRED for STAC API versions 1.0.0-beta.1 and later.", - "type": "array", - "items": { - "type": "string", - "format": "uri" - }, - "example": [ - "https://api.openeo.org/1.2.0", - "https://api.openeo.org/extensions/commercial-data/0.1.0", - "https://api.openeo.org/extensions/federation/0.1.0", - "https://api.stacspec.org/v1.0.0/collections" - ] - }, - "udf_runtime": { - "type": "object", - "required": [ - "type", - "default" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/object_title" - }, - "description": { - "$ref": "#/components/schemas/description" - }, - "type": { - "type": "string", - "description": "The type of the UDF runtime.\n\nPredefined types are:\n* `language` for Programming Languages and\n* `docker` for Docker Containers.\n\nThe types can potentially be extended by back-ends." - }, - "default": { - "type": "string" - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "links": { - "type": "array", - "description": "Links related to this runtime, e.g. external documentation.\n\nIt is highly RECOMMENDED to provide at least links with\nthe following `rel` (relation) types:\n\n1. `about`: A resource that further explains the runtime,\ne.g. a user guide or the documentation. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - } - }, - "discriminator": { - "propertyName": "type", - "mapping": { - "language": "#/components/schemas/udf_programming_language", - "docker": "#/components/schemas/udf_docker" - } - } - }, - "udf_programming_language": { - "allOf": [ - { - "$ref": "#/components/schemas/udf_runtime" - }, - { - "title": "Programming language", - "required": [ - "versions" - ], - "properties": { - "default": { - "type": "string", - "description": "The default version. MUST be one of the keys in the `versions` object." - }, - "versions": { - "title": "Programming language versions", - "description": "Versions available for the programming language.", - "type": "object", - "additionalProperties": { - "x-additionalPropertiesName": "Programming Language Version", - "title": "Programming language version", - "type": "object", - "required": [ - "libraries" - ], - "properties": { - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "libraries": { - "description": "Map of installed libraries, modules, packages or extensions for the programming language. The names of them are used as the property keys.", - "additionalProperties": { - "x-additionalPropertiesName": "Library Name", - "title": "Programming language library", - "type": "object", - "required": [ - "version" - ], - "properties": { - "version": { - "type": "string", - "description": "Version number of the library." - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "links": { - "type": "array", - "description": "Additional links related to this library,\ne.g. external documentation for this library.\n\nIt is highly RECOMMENDED to provide links with\nthe following `rel` (relation) types:\n\n1. `about`: A resource that further explains the library,\ne.g. a user guide or the documentation. It is RECOMMENDED to \nadd descriptive titles for a better user experience.\n\n2. `latest-version`: If a library has been marked as deprecated,\na link SHOULD point to either a new library replacing the deprecated\nlibrary or a latest version of the library available at the back-end.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - } - } - } - } - } - } - } - } - } - ] - }, - "udf_docker": { - "allOf": [ - { - "$ref": "#/components/schemas/udf_runtime" - }, - { - "title": "Docker container", - "required": [ - "docker", - "tags" - ], - "properties": { - "docker": { - "type": "string", - "description": "Identifier of a Docker image on Docker Hub or a private repository, which can run openEO UDFs. This is what is used in the `docker pull` command excluding the tag, e.g. `php`, `mcr.microsoft.com/dotnet/runtime` or `myregistry.local:5000/testing/test-image`." - }, - "default": { - "type": "string", - "description": "The default tag. MUST be one of the values in the `tags` array." - }, - "tags": { - "type": "array", - "description": "The docker tags that are supported.", - "minItems": 1, - "items": { - "type": "string" - } - } - } - } - ] - }, - "result_status": { - "type": "string", - "enum": [ - "running", - "canceled", - "finished", - "error" - ], - "description": "The status of a batch job.\n\nThis field is REQUIRED if the `partial` parameter is given.\nThis field is strongly RECOMMENDED if the job has stopped due to an error.", - "default": "finished" - }, - "batch_job_result": { - "title": "Batch Job Results Response as STAC Item", - "description": "The STAC specification should be the main guidance for implementing this.\nSpecifying the `bbox` is strongly RECOMMENDED for STAC compliance, but can be omitted if the result is unlocated and the `geometry` is set to `null`.", - "type": "object", - "required": [ - "stac_version", - "id", - "type", - "geometry", - "properties", - "assets", - "links" - ], - "properties": { - "stac_version": { - "$ref": "#/components/schemas/stac_version" - }, - "stac_extensions": { - "$ref": "#/components/schemas/stac_extensions" - }, - "id": { - "$ref": "#/components/schemas/job_id" - }, - "type": { - "type": "string", - "description": "The GeoJSON type that applies to this metadata document, which MUST always be a \"Feature\" according to the STAC specification.\nThis type does **not** describe the spatial data type of the assets.", - "enum": [ - "Feature" - ] - }, - "bbox": { - "$ref": "#/components/schemas/bbox" - }, - "geometry": { - "description": "Defines the full footprint of the asset represented by this item as\nGeoJSON Geometry.\n\nResults without a known location can set this value to `null`.", - "nullable": true, - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - } - ], - "example": { - "type": "Polygon", - "coordinates": [ - [ - [ - -180, - -90 - ], - [ - 180, - -90 - ], - [ - 180, - 90 - ], - [ - -180, - 90 - ], - [ - -180, - -90 - ] - ] - ] - } - }, - "properties": { - "type": "object", - "title": "Item Properties", - "description": "MAY contain additional properties other than the required property `datetime`, e.g. custom properties or properties from the STAC specification or STAC extensions.", - "required": [ - "datetime" - ], - "additionalProperties": true, - "properties": { - "datetime": { - "title": "Date and Time", - "description": "The searchable date/time of the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.\n\nIf this field is set to `null` (usually for larger time ranges), it is STRONGLY RECOMMENDED to specify both `start_datetime` and `end_datetime` for STAC compliance.", - "type": "string", - "format": "date-time", - "nullable": true - }, - "start_datetime": { - "type": "string", - "format": "date-time", - "description": "For time series: The first or start date and time for the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." - }, - "end_datetime": { - "type": "string", - "format": "date-time", - "description": "For time series: The last or end date and time for the data, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." - }, - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "license": { - "$ref": "#/components/schemas/stac_license" - }, - "providers": { - "$ref": "#/components/schemas/stac_providers" - }, - "created": { - "$ref": "#/components/schemas/created" - }, - "updated": { - "$ref": "#/components/schemas/updated" - }, - "expires": { - "type": "string", - "format": "date-time", - "description": "Time until which the assets are accessible, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2020-11-01T00:00:00Z" - }, - "openeo:status": { - "$ref": "#/components/schemas/result_status" - } - } - }, - "assets": { - "$ref": "#/components/schemas/stac_assets" - }, - "links": { - "type": "array", - "description": "Links related to this batch job result, e.g. a link to an \ninvoice, additional log files or external documentation.\n\nThe links MUST NOT contain links to the processed and\ndownloadable data. Instead specify these in the `assets` property.\nClients MUST NOT download the data referenced in the links by\ndefault.\n\nIt is **strongly recommended** to add a link with relation type\n`canonical`, which points to this STAC document using a signed URL.\nThis way the STAC metadata can be used by non-openEO clients\nwithout additional authentication steps.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "rel": "canonical", - "type": "application/geo+json", - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/item.json" - } - ] - } - } - }, - "file_format": { - "x-additionalPropertiesName": "File Format Name", - "title": "File Format", - "type": "object", - "description": "Describes a specific file format.", - "required": [ - "gis_data_types", - "parameters" - ], - "properties": { - "title": { - "$ref": "#/components/schemas/object_title" - }, - "description": { - "$ref": "#/components/schemas/description" - }, - "gis_data_types": { - "type": "array", - "description": "Specifies the supported GIS spatial data types for this format.\nIt is RECOMMENDED to specify at least one of the data types, which will likely become a requirement in a future API version.", - "items": { - "type": "string", - "enum": [ - "raster", - "vector", - "table", - "pointcloud", - "other" - ] - } - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "parameters": { - "title": "File Format Parameters", - "description": "Specifies the supported parameters for this file format.", - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/resource_parameter" - } - }, - "links": { - "type": "array", - "description": "Links related to this file format, e.g. external documentation.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - } - } - }, - "production": { - "type": "boolean", - "description": "Specifies whether the implementation is ready to be used in production use (`true`) or not (`false`).\nClients SHOULD only connect to non-production implementations if the user explicitly confirmed to use a non-production implementation.\nThis flag is part of `GET /.well-known/openeo` and `GET /`. It MUST be used consistently in both endpoints.", - "default": false - }, - "links_pagination": { - "description": "Links related to this list of resources, for example links for pagination\nor alternative formats such as a human-readable HTML version.\nThe links array MUST NOT be paginated.\n\nIf pagination is implemented, the following `rel` (relation) types apply:\n\n1. `next` (REQUIRED): A link to the next page, except on the last page.\n\n2. `prev` (OPTIONAL): A link to the previous page, except on the first page.\n\n3. `first` (OPTIONAL): A link to the first page, except on the first page.\n\n4. `last` (OPTIONAL): A link to the last page, except on the last page.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - } - }, - "link": { - "title": "Link", - "description": "A link to another resource on the web. Bases on [RFC 5899](https://www.rfc-editor.org/rfc/rfc5988.html).", - "type": "object", - "required": [ - "href", - "rel" - ], - "properties": { - "rel": { - "type": "string", - "description": "Relationship between the current document and the linked document. SHOULD be a [registered link relation type](https://www.iana.org/assignments/link-relations/link-relations.xml) whenever feasible.", - "example": "related" - }, - "href": { - "type": "string", - "description": "The value MUST be a valid URL.", - "format": "uri", - "example": "https://openeo.example" - }, - "type": { - "type": "string", - "description": "The value MUST be a string that hints at the format used to represent data at the provided URI, preferably a media (MIME) type.", - "example": "text/html" - }, - "title": { - "type": "string", - "description": "Used as a human-readable label for a link.", - "example": "openEO" - } - } - }, - "asset": { - "title": "STAC Asset", - "type": "object", - "required": [ - "href" - ], - "properties": { - "href": { - "title": "Asset location", - "description": "URL to the downloadable asset.\nThe URLs SHOULD be available without authentication so that external clients can download them easily. If the data is confidential, signed URLs SHOULD be used to protect against unauthorized access from third parties.", - "type": "string" - }, - "title": { - "description": "The displayed title for clients and users.", - "type": "string" - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "Multi-line description to explain the asset.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich\ntext representation." - }, - "type": { - "title": "Media Type", - "description": "Media type of the asset.", - "type": "string", - "example": "image/tiff; application=geotiff" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Purposes of the asset. Can be any value, but commonly used values are:\n\n* `thumbnail`: A visualization of the data, usually a lower-resolution true color image in JPEG or PNG format.\n* `reproducibility`: Information how the data was produced and/or can be reproduced, e.g. the process graph used to compute the data in JSON format.\n* `data`: The computed data in the format specified by the user in the process graph (applicable in `GET /jobs/{job_id}/results` only).\n* `metadata`: Additional metadata available for the computed data.", - "example": [ - "data" - ] - } - } - }, - "money": { - "description": "An amount of money or credits. The value MUST be specified in the currency the back-end is working with. The currency can be retrieved by calling `GET /`. If no currency is set, this field MUST be `null`.", - "type": "number", - "minimum": 0, - "example": 12.98, - "nullable": true, - "default": null - }, - "budget": { - "type": "number", - "minimum": 0, - "nullable": true, - "description": "Maximum amount of costs the request is allowed to produce.\nThe value MUST be specified in the currency of the back-end.\nNo limits apply, if the value is `null` or the back-end has no currency\nset in `GET /`.", - "example": 100, - "default": null - }, - "budget_update": { - "type": "number", - "minimum": 0, - "nullable": true, - "description": "Maximum amount of costs the request is allowed to produce.\nThe value MUST be specified in the currency of the back-end.\nNo limits apply, if the value is `null`.", - "example": 100 - }, - "billing_plan": { - "type": "string", - "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be handled in a *case insensitive* manner.\n\nThe plans can be retrieved from `GET /`, but the value returned here may\nnot be in the list of plans any longer.", - "example": "free" - }, - "billing_plan_null": { - "type": "string", - "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be accepted in a *case insensitive* manner.\nBack-ends MUST resolve the billing plan in the following way if billing is supported:\n\n* If a value is given and it is not `null`: Persist the `plan` that has been provided in the request.\n* Otherwise, don't change the billing plan.\n\nBilling plans not on the list of available plans MUST be rejected with\nopenEO error `BillingPlanInvalid`.", - "example": "free", - "nullable": true - }, - "billing_plan_null_default": { - "type": "string", - "description": "The billing plan to process and charge the job or service with.\n\nBilling plans MUST be accepted in a *case insensitive* manner.\nBack-ends MUST resolve the billing plan in the following way:\n\n* If a non-`null` value is given: Persist the `plan` that has been provided in the request.\n* Otherwise:\n 1. Persist the `default_plan` exposed through `GET /me`, if available.\n 2. Persist the `default_plan` exposed through `GET /`, if available.\n 3. If a single plan is exposed by the back-end, persist it.\n 4. Otherwise, the back-end MUST throw a `BillingPlanMissing` error.\n\nThe resolved plan MUST be persisted permanently, regardless of any \nchanges to the exposed billing plans in `GET /` in the future.\n\nBilling plans not on the list of available plans MUST be rejected with\nopenEO error `BillingPlanInvalid`.", - "example": "free", - "nullable": true, - "default": null - }, - "collection": { - "title": "Collection", - "type": "object", - "required": [ - "stac_version", - "id", - "description", - "license", - "extent", - "links" - ], - "properties": { - "stac_version": { - "$ref": "#/components/schemas/stac_version" - }, - "stac_extensions": { - "$ref": "#/components/schemas/stac_extensions" - }, - "type": { - "type": "string", - "enum": [ - "Collection" - ], - "description": "For STAC versions >= 1.0.0-rc.1 this field is required." - }, - "id": { - "$ref": "#/components/schemas/collection_id" - }, - "title": { - "type": "string", - "description": "A short descriptive one-line title for the collection." - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "Detailed multi-line description to explain the collection.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation." - }, - "keywords": { - "type": "array", - "description": "List of keywords describing the collection.", - "items": { - "type": "string" - } - }, - "version": { - "type": "string", - "description": "Version of the collection.\n\nThis property REQUIRES to add `version` (STAC < 1.0.0-rc.1) or\n`https://stac-extensions.github.io/version/v1.2.0/schema.json` (STAC >= 1.0.0-rc.1)\nto the list of `stac_extensions`." - }, - "deprecated": { - "type": "boolean", - "default": false, - "description": "Specifies that the collection is deprecated with the potential to\nbe removed. It should be transitioned out of usage as soon as\npossible and users should refrain from using it in new projects.\n\nA link with relation type `latest-version` SHOULD be added to the\nlinks and MUST refer to the collection that can be used instead.\n\nThis property REQUIRES to add `version` (STAC < 1.0.0-rc.1) or\n`https://stac-extensions.github.io/version/v1.2.0/schema.json` (STAC >= 1.0.0-rc.1)\nto the list of `stac_extensions`." - }, - "license": { - "$ref": "#/components/schemas/stac_license" - }, - "providers": { - "$ref": "#/components/schemas/stac_providers" - }, - "extent": { - "type": "object", - "title": "Collection Extent", - "description": "The extent of the data in the collection. Additional members MAY\nbe added to represent other extents, for example, thermal or\npressure ranges.\n\nThe first item in the array always describes the overall extent of\nthe data. All subsequent items describe more preciseextents,\ne.g. to identify clusters of data.\nClients only interested in the overall extent will only need to\naccess the first item in each array.", - "required": [ - "spatial", - "temporal" - ], - "properties": { - "spatial": { - "title": "Collection Spatial Extent", - "description": "The *potential* spatial extents of the features in the collection.", - "type": "object", - "properties": { - "bbox": { - "description": "One or more bounding boxes that describe the spatial extent\nof the dataset.\n\nThe first bounding box describes the overall spatial extent\nof the data. All subsequent bounding boxes describe more\nprecise bounding boxes, e.g. to identify clusters of data.\nClients only interested in the overall spatial extent will\nonly need to access the first item in each array.", - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/bbox" - } - } - } - }, - "temporal": { - "title": "Collection Temporal Extent", - "description": "The *potential* temporal extents of the features in the collection.", - "type": "object", - "properties": { - "interval": { - "description": "One or more time intervals that describe the temporal extent\nof the dataset.\n\nThe first time interval describes the overall temporal extent\nof the data. All subsequent time intervals describe more\nprecise time intervals, e.g. to identify clusters of data.\nClients only interested in the overall extent will only need\nto access the first item in each array.", - "type": "array", - "minItems": 1, - "items": { - "description": "Begin and end times of the time interval. The coordinate\nreference system is the Gregorian calendar.\n\nThe value `null` is supported and indicates an open time\ninterval.", - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { - "type": "string", - "format": "date-time", - "nullable": true - }, - "example": [ - "2011-11-11T12:22:11Z", - null - ] - } - } - } - } - } - }, - "links": { - "description": "Links related to this collection.\nCould reference to licensing information, other meta data formats with\nadditional information or a preview image.\n\nIt is RECOMMENDED to provide links with the following\n`rel` (relation) types:\n\n1. `root` and `parent`: URL to the data discovery endpoint at `/collections`.\n\n2. `license`: A link to the license(s) SHOULD be specified if the `license`\nfield is set to `proprietary` or `various`.\n\n3. `example`: Links to examples of processes that use this collection.\n\n4. `latest-version`: If a collection has been marked as deprecated, a link SHOULD\npoint to the latest version of the collection. The relation types `predecessor-version`\n(link to older version) and `successor-version` (link to newer version) can also be used\nto show the relation between versions.\n\n5. `alternate`: An alternative representation of the collection.\nFor example, this could be the collection available through another\ncatalog service such as OGC CSW, a human-readable HTML version or a\nmetadata document following another standard such as ISO 19115 or DCAT.\n\n6. `http://www.opengis.net/def/rel/ogc/1.0/queryables`: URL to the\nqueryables endpoint at `/collections/{collection_id}/queryables`.\nFor JSON Schema documents, the `type` field must be set to `application/schema+json`.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking)\nand the STAC specification for Collections.", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - } - }, - "cube:dimensions": { - "title": "STAC Collection Cube Dimensions", - "description": "The named default dimensions of the data cube.\nNames must be unique per collection.\n\nThe keys of the object are the dimension names. For\ninteroperability, it is RECOMMENDED to use the\nfollowing dimension names if there is only a single\ndimension with the specified criteria:\n\n* `x` for the dimension of type `spatial` with the axis set to `x`\n* `y` for the dimension of type `spatial` with the axis set to `y`\n* `z` for the dimension of type `spatial` with the axis set to `z`\n* `t` for the dimension of type `temporal`\n* `bands` for dimensions of type `bands`\n* `geometry` for dimensions of type `geometry`\n\nThis property REQUIRES to add a version of the data cube extension to the list\nof `stac_extensions`, e.g. `https://stac-extensions.github.io/datacube/v2.2.0/schema.json`.", - "type": "object", - "additionalProperties": { - "x-additionalPropertiesName": "Dimension Name", - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - } - ] - } - }, - "summaries": { - "title": "STAC Summaries (Collection Properties)", - "description": "Collection properties from STAC extensions (e.g. EO,\nSAR, Satellite or Scientific) or even custom extensions.\n\nSummaries are either a unique set of all available\nvalues, statistics *or* a JSON Schema. Statistics only\nspecify the range (minimum and maximum values) by default,\nbut can optionally be accompanied by additional\nstatistical values. The range can specify the\npotential range of values, but it is recommended to be\nas precise as possible. The set of values MUST contain\nat least one element and it is strongly RECOMMENDED to\nlist all values. It is recommended to list as many\nproperties as reasonable so that consumers get a full\noverview of the Collection. Properties that are\ncovered by the Collection specification (e.g.\n`providers` and `license`) SHOULD NOT be repeated in the\nsummaries.\n\nPotential fields for the summaries can be found here:\n\n* **[STAC Common Metadata](https://github.com/radiantearth/stac-spec/blob/v1.0.0/item-spec/common-metadata.md)**:\n A list of commonly used fields throughout all domains\n* **[Content Extensions](https://github.com/radiantearth/stac-spec/blob/v1.0.0/extensions/README.md#list-of-content-extensions)**:\n Domain-specific fields for domains such as EO, SAR and point clouds.\n* **Custom Properties**:\n It is generally allowed to add custom fields.", - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "type": "array", - "title": "Set of values", - "items": { - "description": "A value of any type." - } - }, - { - "$ref": "#/components/schemas/collection_summary_stats" - }, - { - "$ref": "#/components/schemas/json_schema" - } - ] - } - }, - "assets": { - "description": "Dictionary of asset objects for data that can be downloaded,\neach with a unique key.\nThe keys MAY be used by clients as file names.\n\nImplementing this property REQUIRES to add `collection-assets`\nto the list of `stac_extensions` in STAC < 1.0.0-rc.1.", - "allOf": [ - { - "$ref": "#/components/schemas/stac_assets" - } - ] - } - } - }, - "stac_version": { - "type": "string", - "description": "The [version of the STAC specification](https://github.com/radiantearth/stac-spec/releases), which MAY not be equal to the [STAC API version](#tag/EO-Data-Discovery/STAC). Supports versions 0.9.x and 1.x.x.", - "pattern": "^(0\\.9.\\d+|1\\.\\d+.\\d+)", - "example": "1.0.0" - }, - "stac_extensions": { - "type": "array", - "description": "A list of implemented STAC extensions. The list contains URLs to the JSON Schema files it can be validated against. For STAC < 1.0.0-rc.1 shortcuts such as `sar` can be used instead of the schema URL.", - "uniqueItems": true, - "items": { - "anyOf": [ - { - "title": "Reference to a JSON Schema", - "type": "string", - "format": "uri", - "example": "https://openeo.example/stac/custom-extemsion/v1.0.0/schema.json" - }, - { - "title": "Reference to a core extension (STAC < 1.0.0-rc.1 only)", - "type": "string", - "example": "datacube" - } - ] - } - }, - "stac_license": { - "type": "string", - "description": "License(s) of the data as a SPDX [License identifier](https://spdx.org/licenses/).\nAlternatively, use `proprietary` if the license is not on the SPDX\nlicense list or `various` if multiple licenses apply. In these two cases\nlinks to the license texts SHOULD be added, see the `license` link\nrelation type.\n\nNon-SPDX licenses SHOULD add a link to the license text with the\n`license` relation in the links section. The license text MUST NOT be\nprovided as a value of this field. If there is no public license URL\navailable, it is RECOMMENDED to host the license text and link to it.", - "example": "Apache-2.0" - }, - "stac_providers": { - "type": "array", - "description": "A list of providers, which MAY include all organizations capturing or processing the data or the hosting provider. Providers SHOULD be listed in chronological order with the most recent provider being the last element of the list.", - "items": { - "type": "object", - "title": "Provider", - "required": [ - "name" - ], - "properties": { - "name": { - "description": "The name of the organization or the individual.", - "type": "string", - "example": "Example Cloud Corp." - }, - "description": { - "description": "Multi-line description to add further provider information such as processing details for processors and producers, hosting details for hosts or basic contact information.\n\nCommonMark 0.29 syntax MAY be used for rich text representation.", - "type": "string", - "example": "No further processing applied." - }, - "roles": { - "description": "Roles of the provider.\n\nThe provider's role(s) can be one or more of the following\nelements:\n* `licensor`: The organization that is licensing the dataset under\nthe license specified in the collection's license field.\n* `producer`: The producer of the data is the provider that\ninitially captured and processed the source data, e.g. ESA for\nSentinel-2 data.\n* `processor`: A processor is any provider who processed data to a\nderived product.\n* `host`: The host is the actual provider offering the data on their\nstorage. There SHOULD be no more than one host, specified as last\nelement of the list.", - "type": "array", - "items": { - "type": "string", - "enum": [ - "producer", - "licensor", - "processor", - "host" - ] - }, - "example": [ - "producer", - "licensor", - "host" - ] - }, - "url": { - "description": "Homepage on which the provider describes the dataset and publishes contact information.", - "type": "string", - "format": "uri", - "example": "https://cloud.example" - } - } - } - }, - "stac_assets": { - "type": "object", - "title": "Assets", - "description": "Dictionary of asset objects for data that can be downloaded, each with a\nunique key. The keys MAY be used by clients as file names.", - "additionalProperties": { - "$ref": "#/components/schemas/asset" - }, - "example": { - "preview.png": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/preview.png", - "type": "image/png", - "title": "Thumbnail", - "roles": [ - "thumbnail" - ] - }, - "process.json": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/process.json", - "type": "application/json", - "title": "Original Process", - "roles": [ - "process", - "reproduction" - ] - }, - "1.tif": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/1.tif", - "type": "image/tiff; application=geotiff", - "title": "Band 1", - "roles": [ - "data" - ] - }, - "2.tif": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/2.tif", - "type": "image/tiff; application=geotiff", - "title": "Band 2", - "roles": [ - "data" - ] - }, - "inspire.xml": { - "href": "https://openeo.example/api/v1/download/583fba8b2ce583fba8b2ce/inspire.xml", - "type": "application/xml", - "title": "INSPIRE metadata", - "description": "INSPIRE compliant XML metadata", - "roles": [ - "metadata" - ] - } - } - }, - "collection_summary_stats": { - "type": "object", - "title": "Statistics / Range", - "description": "By default, only ranges with a minimum and a maximum value can be specified. Ranges can be specified for ordinal values only, which means they need to have a rank order. Therefore, ranges can only be specified for numbers and some special types of strings. Examples: grades (A to F), dates or times. Implementors are free to add other derived statistical values to the object, for example `mean` or `stddev`.", - "required": [ - "minimum", - "maximum" - ], - "properties": { - "minimum": { - "description": "The minimum value (inclusive).", - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - }, - "maximum": { - "description": "The maximum value (inclusive).", - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - } - }, - "bbox": { - "description": "Each bounding box is provided as four or six numbers,\ndepending on whether the coordinate reference system\nincludes a vertical axis (height or depth):\n\n* West (lower left corner, coordinate axis 1)\n* South (lower left corner, coordinate axis 2)\n* Base (optional, minimum value, coordinate axis 3)\n* East (upper right corner, coordinate axis 1)\n* North (upper right corner, coordinate axis 2)\n* Height (optional, maximum value, coordinate axis 3)\n\nThe coordinate reference system of the values is WGS 84\nlongitude/latitude (http://www.opengis.net/def/crs/OGC/1.3/CRS84).\n\nFor WGS 84 longitude/latitude the values are in most cases\nthe sequence of minimum longitude, minimum latitude, maximum\nlongitude and maximum latitude.\n\nHowever, in cases where the box spans the antimeridian the\nfirst value (west-most box edge) is larger than the third value\n(east-most box edge).\n\nIf the vertical axis is included, the third and the sixth\nnumber are the bottom and the top of the 3-dimensional bounding box.", - "type": "array", - "oneOf": [ - { - "title": "4 elements", - "minItems": 4, - "maxItems": 4 - }, - { - "title": "6 elements", - "minItems": 6, - "maxItems": 6 - } - ], - "items": { - "type": "number" - }, - "example": [ - -180, - -90, - 180, - 90 - ] - }, - "collection_id": { - "type": "string", - "description": "A unique identifier for the collection, which MUST match the specified pattern.", - "pattern": "^[\\w\\-\\.~\\/]+$", - "example": "Sentinel-2A" - }, - "dimension": { - "title": "Dimension", - "description": "A dimension, each object represents a distinct dimension with the key being the dimension name.", - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "description": "Type of the dimension.", - "type": "string", - "enum": [ - "spatial", - "temporal", - "bands", - "geometry", - "other" - ] - }, - "description": { - "$ref": "#/components/schemas/description" - } - }, - "discriminator": { - "propertyName": "type", - "mapping": { - "spatial": "#/components/schemas/dimension_spatial", - "temporal": "#/components/schemas/dimension_temporal", - "bands": "#/components/schemas/dimension_bands", - "geometry": "#/components/schemas/dimension_geometry", - "other": "#/components/schemas/dimension_other" - } - } - }, - "dimension_other": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Additional Dimension", - "type": "object", - "properties": { - "extent": { - "$ref": "#/components/schemas/collection_dimension_extent_open" - }, - "values": { - "$ref": "#/components/schemas/collection_dimension_values" - }, - "step": { - "$ref": "#/components/schemas/collection_dimension_step" - }, - "unit": { - "$ref": "#/components/schemas/collection_dimension_unit" - }, - "reference_system": { - "description": "The reference system for the dimension.", - "type": "string" - } - } - } - ] - }, - "dimension_geometry": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Geometry Dimension", - "type": "object", - "required": [ - "bbox" - ], - "properties": { - "axes": { - "description": "Axes of the vector dimension as an ordered set of `x`, `y` and `z`. Defaults to `x` and `y`.", - "default": [ - "x", - "y" - ], - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/dimension_axis_xyz" - } - }, - "bbox": { - "$ref": "#/components/schemas/bbox" - }, - "values": { - "description": "Optionally, a representation of the vectors. This can be a list of WKT string or other free-form identifiers.", - "type": "array", - "items": { - "type": "string" - } - }, - "geometry_types": { - "description": "A set of all geometry types included in this dimension. If not present, mixed geometry types must be assumed.", - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/geometry_type" - } - }, - "reference_system": { - "$ref": "#/components/schemas/collection_dimension_srs" - } - } - } - ] - }, - "dimension_bands": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Band Dimension", - "description": "A dimension for the bands.\n\nThe band dimension only specifies the band names\nas dimension labels. Further information to the\nbands are available in either `sar:bands` or\n`eo:bands` in the `summaries` property.", - "type": "object", - "required": [ - "values" - ], - "properties": { - "values": { - "$ref": "#/components/schemas/collection_dimension_values" - } - } - } - ] - }, - "dimension_spatial": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Spatial Dimension", - "description": "A spatial (raster) dimension in one of the horizontal (x or y) or vertical (z) directions.", - "type": "object", - "required": [ - "axis" - ], - "properties": { - "axis": { - "$ref": "#/components/schemas/dimension_axis_xyz" - }, - "extent": { - "description": "Extent (lower and upper bounds) of the dimension as two-dimensional array. Open intervals with `null` are not allowed.", - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { - "type": "number" - } - }, - "values": { - "description": "A set of all potential values.", - "type": "array", - "minItems": 1, - "items": { - "type": "number" - } - }, - "step": { - "$ref": "#/components/schemas/collection_dimension_step" - }, - "reference_system": { - "$ref": "#/components/schemas/collection_dimension_srs" - } - }, - "discriminator": { - "propertyName": "axis", - "mapping": { - "x": "#/components/schemas/dimension_spatial_horizontal", - "y": "#/components/schemas/dimension_spatial_horizontal", - "z": "#/components/schemas/dimension_spatial_vertical" - } - } - } - ] - }, - "dimension_axis_xyz": { - "title": "Axis", - "description": "Axis of a geometry or dimension (`x`, `y` or `z`)", - "type": "string", - "enum": [ - "x", - "y", - "z" - ] - }, - "dimension_spatial_horizontal": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension_spatial" - }, - { - "title": "Horizontal Spatial Dimension", - "required": [ - "extent" - ] - } - ] - }, - "dimension_spatial_vertical": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension_spatial" - }, - { - "title": "Vertical Spatial Dimension", - "anyOf": [ - { - "title": "Vertical Spatial Dimension with Extent", - "required": [ - "extent" - ] - }, - { - "title": "Vertical Spatial Dimension with Values", - "required": [ - "values" - ] - } - ] - } - ] - }, - "dimension_temporal": { - "allOf": [ - { - "$ref": "#/components/schemas/dimension" - }, - { - "title": "Temporal Dimension", - "description": "A temporal dimension based on the ISO 8601 standard. The temporal reference system for the data is expected to be ISO 8601 compliant (Gregorian calendar / UTC). Data not compliant with ISO 8601 can be represented as an *Additional Dimension Object* with `type` set to `temporal`.", - "type": "object", - "required": [ - "extent" - ], - "properties": { - "values": { - "description": "If the dimension consists of set of specific values they can be listed here. The dates and/or times MUST be strings compliant to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601).", - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - }, - "extent": { - "description": "Extent (lower and upper bounds) of the dimension as two-dimensional array. The dates and/or times MUST be strings compliant to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601). `null` is allowed for open date ranges.", - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { - "type": "string", - "nullable": true - } - }, - "step": { - "description": "The space between the temporal instances as [ISO 8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations), e.g. `P1D`. Use `null` for irregularly spaced steps.", - "type": "string", - "nullable": true - } - } - } - ] - }, - "collection_dimension_srs": { - "title": "Spatial reference system", - "description": "The spatial reference system for the data, specified as [EPSG code](http://www.epsg-registry.org/), [WKT2 (ISO 19162) string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html), [PROJJSON object](https://proj.org/specifications/projjson.html) or [PROJ definition (deprecated)](https://proj.org/usage/quickstart.html). Defaults to EPSG code 4326.", - "default": 4326, - "oneOf": [ - { - "type": "number", - "title": "EPSG code" - }, - { - "type": "string", - "title": "WKT2 or PROJ definition (deprecated)" - }, - { - "type": "object", - "title": "PROJJSON" - } - ] - }, - "collection_dimension_extent_open": { - "description": "If the dimension consists of [ordinal](https://en.wikipedia.org/wiki/Level_of_measurement#Ordinal_scale) values, the extent (lower and upper bounds) of the values as two-dimensional array. Use `null` for open intervals.", - "type": "array", - "minItems": 2, - "maxItems": 2, - "items": { - "type": "number", - "nullable": true - } - }, - "collection_dimension_values": { - "description": "A set of all potential values, especially useful for [nominal](https://en.wikipedia.org/wiki/Level_of_measurement#Nominal_level) values.\n\n**Important:** The order of the values MUST be exactly how the dimension values are also ordered in the data (cube). If the values specify band names, the values MUST be in the same order as they are in the corresponding band fields (i.e. `eo:bands` or `sar:bands`).", - "type": "array", - "minItems": 1, - "items": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] - } - }, - "collection_dimension_step": { - "description": "If the dimension consists of [interval](https://en.wikipedia.org/wiki/Level_of_measurement#Interval_scale) values, the space between the values. Use `null` for irregularly spaced steps.", - "type": "number", - "nullable": true - }, - "collection_dimension_unit": { - "description": "The unit of measurement for the data, preferably compliant to [UDUNITS-2](https://ncics.org/portfolio/other-resources/udunits2/) units (singular).", - "type": "string" - }, - "process_arguments": { - "title": "Process Arguments", - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/process_argument_value" - } - }, - "process_argument_value": { - "title": "Process Argument Value", - "description": "Arguments for a process. See the API documentation for more information.", - "nullable": true, - "anyOf": [ - { - "type": "object", - "nullable": true, - "title": "Object (restricted)", - "properties": { - "from_parameter": { - "not": {} - }, - "from_node": { - "not": {} - }, - "process_graph": { - "not": {} - } - } - }, - { - "type": "string", - "title": "String" - }, - { - "type": "number", - "title": "Number (incl. integers)" - }, - { - "type": "boolean", - "title": "Boolean" - }, - { - "type": "array", - "title": "Array", - "items": { - "$ref": "#/components/schemas/process_argument_value" - } - }, - { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - { - "type": "object", - "title": "Result Reference", - "description": "Data that is expected to be passed from another process.", - "required": [ - "from_node" - ], - "properties": { - "from_node": { - "description": "The ID of the node that data is expected to come from.", - "type": "string" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "title": "Parameter Reference", - "description": "A parameter for a process graph. Data that is expected to be passed to a process graph either from the user directly or from the process that is executing the process graph.", - "required": [ - "from_parameter" - ], - "properties": { - "from_parameter": { - "description": "The name of the parameter that data is expected to come from.", - "type": "string" - } - }, - "additionalProperties": false - } - ] - }, - "process_graph": { - "title": "Process Graph", - "description": "A process graph defines a graph-like structure as a connected set of executable processes. Each key is a unique identifier (node ID) that is used to refer to the process in the graph.", - "type": "object", - "additionalProperties": { - "x-additionalPropertiesName": "Node ID", - "title": "Process Node", - "type": "object", - "required": [ - "process_id", - "arguments" - ], - "properties": { - "process_id": { - "$ref": "#/components/schemas/process_id" - }, - "namespace": { - "$ref": "#/components/schemas/process_namespace" - }, - "result": { - "type": "boolean", - "description": "Used to specify which node is the last in the chain and returns the result to return to the requesting context. This flag MUST only be set once in each list of process nodes.", - "default": false - }, - "description": { - "description": "Optional description about the process and its arguments.", - "type": "string", - "nullable": true - }, - "arguments": { - "$ref": "#/components/schemas/process_arguments" - } - } - }, - "example": { - "dc": { - "process_id": "load_collection", - "arguments": { - "id": "Sentinel-2", - "spatial_extent": { - "west": 16.1, - "east": 16.6, - "north": 48.6, - "south": 47.2 - }, - "temporal_extent": [ - "2018-01-01", - "2018-02-01" - ] - } - }, - "bands": { - "process_id": "filter_bands", - "description": "Filter and order the bands. The order is important for the following reduce operation.", - "arguments": { - "data": { - "from_node": "dc" - }, - "bands": [ - "B08", - "B04", - "B02" - ] - } - }, - "evi": { - "process_id": "reduce", - "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", - "arguments": { - "data": { - "from_node": "bands" - }, - "dimension": "bands", - "reducer": { - "process_graph": { - "nir": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" - }, - "index": 0 - } - }, - "red": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" - }, - "index": 1 - } - }, - "blue": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" - }, - "index": 2 - } - }, - "sub": { - "process_id": "subtract", - "arguments": { - "data": [ - { - "from_node": "nir" - }, - { - "from_node": "red" - } - ] - } - }, - "p1": { - "process_id": "product", - "arguments": { - "data": [ - 6, - { - "from_node": "red" - } - ] - } - }, - "p2": { - "process_id": "product", - "arguments": { - "data": [ - -7.5, - { - "from_node": "blue" - } - ] - } - }, - "sum": { - "process_id": "sum", - "arguments": { - "data": [ - 1, - { - "from_node": "nir" - }, - { - "from_node": "p1" - }, - { - "from_node": "p2" - } - ] - } - }, - "div": { - "process_id": "divide", - "arguments": { - "data": [ - { - "from_node": "sub" - }, - { - "from_node": "sum" - } - ] - } - }, - "p3": { - "process_id": "product", - "arguments": { - "data": [ - 2.5, - { - "from_node": "div" - } - ] - }, - "result": true - } - } - } - } - }, - "mintime": { - "process_id": "reduce", - "description": "Compute a minimum time composite by reducing the temporal dimension", - "arguments": { - "data": { - "from_node": "evi" - }, - "dimension": "temporal", - "reducer": { - "process_graph": { - "min": { - "process_id": "min", - "arguments": { - "data": { - "from_parameter": "data" - } - }, - "result": true - } - } - } - } - }, - "save": { - "process_id": "save_result", - "arguments": { - "data": { - "from_node": "mintime" - }, - "format": "GTiff" - }, - "result": true - } - } - }, - "process": { - "title": "Process", - "type": "object", - "properties": { - "id": { - "$ref": "#/components/schemas/process_id" - }, - "summary": { - "$ref": "#/components/schemas/process_summary" - }, - "description": { - "$ref": "#/components/schemas/process_description" - }, - "categories": { - "$ref": "#/components/schemas/process_categories" - }, - "parameters": { - "$ref": "#/components/schemas/process_parameters" - }, - "returns": { - "$ref": "#/components/schemas/process_return_value" - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "exceptions": { - "$ref": "#/components/schemas/process_exceptions" - }, - "examples": { - "type": "array", - "description": "Examples, may be used for unit tests.", - "items": { - "title": "Process Example", - "type": "object", - "required": [ - "arguments" - ], - "properties": { - "title": { - "type": "string", - "description": "A title for the example." - }, - "description": { - "$ref": "#/components/schemas/process_description" - }, - "arguments": { - "$ref": "#/components/schemas/process_arguments" - }, - "returns": { - "description": "The return value which can by of any data type." - } - } - } - }, - "links": { - "type": "array", - "description": "Links related to this process, e.g. additional external documentation.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `latest-version`: If a process has been marked as deprecated, a link SHOULD\npoint to the preferred version of the process. The relation types `predecessor-version`\n(link to older version) and `successor-version` (link to newer version) can also be used\nto show the relation between versions.\n\n2. `example`: Links to examples of other processes that use this process.\n\n3. `cite-as`: For all DOIs associated with the process, the respective DOI\nlinks SHOULD be added.\n\nFor additional relation types see also the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - } - }, - "process_graph": { - "$ref": "#/components/schemas/process_graph" - } - } - }, - "user_defined_process_meta": { - "title": "User-defined Process Metadata", - "description": "A user-defined process, may only contain metadata and no process graph.", - "type": "object", - "required": [ - "id" - ], - "properties": { - "summary": { - "type": "string", - "nullable": true - }, - "description": { - "type": "string", - "nullable": true - }, - "parameters": { - "type": "array", - "nullable": true - }, - "returns": { - "type": "object", - "nullable": true - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/process" - } - ] - }, - "process_graph_with_metadata": { - "title": "Process Graph with metadata", - "description": "A process graph, optionally enriched with process metadata.", - "type": "object", - "required": [ - "process_graph" - ], - "properties": { - "id": { - "type": "string", - "nullable": true - }, - "summary": { - "type": "string", - "nullable": true - }, - "description": { - "type": "string", - "nullable": true - }, - "parameters": { - "type": "array", - "nullable": true - }, - "returns": { - "type": "object", - "nullable": true - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/process" - } - ] - }, - "process_namespace": { - "type": "string", - "nullable": true, - "default": null, - "example": null, - "description": "The namespace the `process_id` is valid for.\n\nThe following options are predefined by the openEO API, but additional\nnamespaces may be introduced by back-ends or in a future version of the API.\n\n* `null` (default): Checks both user-defined and predefined processes,\n but prefers user-defined processes if both are available.\n This allows users to add missing predefined processes for portability,\n e.g. common processes from [processes.openeo.org](https://processes.openeo.org)\n that have a process graph included.\n It is RECOMMENDED to log the namespace selected by the back-end for debugging purposes.\n* `backend`: Uses exclusively the predefined processes listed at `GET /processes`.\n* `user`: Uses exclusively the user-defined processes listed at `GET /process_graphs`.\n\nIf multiple processes with the same identifier exist, Clients SHOULD\ninform the user that it's recommended to select a namespace." - }, - "process_id": { - "type": "string", - "description": "The identifier for the process. It MUST be unique across its namespace\n(e.g. predefined processes or user-defined processes).\n\nClients SHOULD warn the user if a user-defined process is added with the \nsame identifier as one of the predefined process.", - "pattern": "^\\w+$", - "example": "ndvi" - }, - "process_summary": { - "type": "string", - "description": "A short summary of what the process does." - }, - "process_categories": { - "type": "array", - "description": "A list of categories.", - "items": { - "type": "string", - "description": "Name of the category." - } - }, - "process_return_value": { - "type": "object", - "title": "Process Return Value", - "description": "Description of the data that is returned by this process.", - "required": [ - "schema" - ], - "properties": { - "description": { - "$ref": "#/components/schemas/process_description" - }, - "schema": { - "$ref": "#/components/schemas/process_schema" - } - } - }, - "experimental": { - "type": "boolean", - "description": "Declares that the specified entity is experimental, which means that it is likely to change or may produce unpredictable behaviour. Users should refrain from using it in production, but still feel encouraged to try it out and give feedback.", - "default": false - }, - "deprecated": { - "type": "boolean", - "description": "Declares that the specified entity is deprecated with the potential\nto be removed in any of the next versions. It should be transitioned out\nof usage as soon as possible and users should refrain from using it in\nnew implementations.", - "default": false - }, - "process_exceptions": { - "type": "object", - "title": "Process Exceptions", - "description": "Declares exceptions (errors) that might occur during execution\nof this process. This list is just for informative purposes and may be\nincomplete. This list MUST only contain exceptions that stop the\nexecution of a process and MUST NOT contain warnings, notices or\ndebugging messages. It is meant to primarily contain errors that\nhave been caused by the user. It is RECOMMENDED that exceptions\nare referred to and explained in process or parameter descriptions.\n\nThe keys define the error code and MUST match the following pattern:\n`^\\w+$`\n\nThis schema follows the schema of the general openEO error list (see\nerrors.json).", - "additionalProperties": { - "x-additionalPropertiesName": "Error Code", - "title": "Process Exception", - "type": "object", - "required": [ - "message" - ], - "properties": { - "description": { - "type": "string", - "format": "commonmark", - "description": "Detailed description to explain the error to client\nusers and back-end developers. This should not be shown in the\nclients directly, but MAY be linked to in the errors `url`\nproperty.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used\nfor rich text representation." - }, - "message": { - "type": "string", - "description": "Explains the reason the server is rejecting the request. This message is intended to be displayed to the client user. For \"4xx\" error codes the message SHOULD explain shortly how the client needs to modify the request.\n\nThe message MAY contain variables, which are enclosed by curly brackets. Example: `{variable_name}`", - "example": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}" - }, - "http": { - "type": "integer", - "description": "HTTP Status Code, following the [error handling conventions in openEO](#section/API-Principles/Error-Handling). Defaults to `400`.", - "default": 400 - } - } - } - }, - "process_parameters": { - "type": "array", - "description": "A list of parameters.\n\nThe order in the array corresponds to the parameter order to\nbe used in clients that don't support named parameters.\n\n**Note:** Specifying an empty array is different from (if allowed)\n`null` or the property being absent.\nAn empty array means the process has no parameters.\n`null` / property absent means that the parameters are unknown as\nthe user has not specified them. There could still be parameters in the\nprocess graph, if one is specified.", - "items": { - "$ref": "#/components/schemas/process_parameter" - } - }, - "base_parameter": { - "type": "object", - "required": [ - "name", - "description" - ], - "properties": { - "name": { - "type": "string", - "description": "A unique name for the parameter. \n\nIt is RECOMMENDED to use [snake case](https://en.wikipedia.org/wiki/Snake_case) (e.g. `window_size` or `scale_factor`).", - "pattern": "^\\w+$" - }, - "description": { - "$ref": "#/components/schemas/process_description" - }, - "optional": { - "type": "boolean", - "description": "Determines whether this parameter is optional to be specified even when no default is specified.\nClients SHOULD automatically set this parameter to `true`, if a default value is specified. Back-ends SHOULD NOT fail, if a default value is specified and this flag is missing.", - "default": false - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "default": { - "description": "The default value for this parameter. Required parameters SHOULD NOT specify a default value. Optional parameters SHOULD always specify a default value." - } - } - }, - "parameter": { - "title": "Parameter", - "type": "object", - "required": [ - "schema" - ], - "properties": { - "schema": { - "$ref": "#/components/schemas/data_type_schema" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/base_parameter" - } - ] - }, - "process_parameter": { - "title": "Process Parameter", - "type": "object", - "required": [ - "schema" - ], - "properties": { - "schema": { - "$ref": "#/components/schemas/process_schema" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/base_parameter" - } - ] - }, - "batch_job": { - "title": "Batch Job", - "description": "The metadata of a batch jobs that has been submitted by the authenticated user.", - "type": "object", - "required": [ - "id", - "status", - "created" - ], - "properties": { - "id": { - "$ref": "#/components/schemas/job_id" - }, - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "status": { - "type": "string", - "enum": [ - "created", - "queued", - "running", - "canceled", - "finished", - "error" - ], - "description": "The current status of a batch job.\n\nThe following status changes can occur:\n* `POST /jobs`: The status is initialized as `created`.\n* `POST /jobs/{job_id}/results`: The status is set to `queued`, if\nprocessing doesn't start instantly.\n * Once the processing starts the status is set to `running`.\n * Once the data is available to download the status is set to `finished`.\n * Whenever an error occurs during processing, the status MUST be set to `error`.\n* `DELETE /jobs/{job_id}/results`: The status is set to `canceled` if\nthe status was `running` beforehand and partial or preliminary results\nare available to be downloaded. Otherwise the status is set to\n`created`. ", - "example": "running", - "default": "created" - }, - "progress": { - "type": "number", - "description": "Indicates the process of a running batch job in percent.\nCan also be set for a job which stopped due to an error or was canceled by the user. In this case, the value indicates the progress at which the job stopped. The Property may not be available for the status codes `created` and `queued`.\nSubmitted and queued jobs only allow the value `0`, finished jobs only allow the value `100`.", - "minimum": 0, - "maximum": 100, - "example": 75.5 - }, - "created": { - "$ref": "#/components/schemas/created" - }, - "updated": { - "$ref": "#/components/schemas/updated" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan" - }, - "costs": { - "$ref": "#/components/schemas/money" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "usage": { - "description": "Metrics about the resource usage of the batch job.\n\nBack-ends are not expected to update the metrics while processing data,\nso the metrics can only be available after the job has finished\nor has stopped due to an error.\nFor usage metrics during processing, metrics can better be added to the\nlogs (e.g. `GET /jobs/{job_id}/logs`) with the same schema.", - "allOf": [ - { - "$ref": "#/components/schemas/usage" - } - ] - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - }, - "links": { - "type": "array", - "description": "Links related to this batch job, e.g. a links to \ninvoices, log files or results.\n\nIt is RECOMMENDED to provide links with the following `rel` (relation) types:\n\n1. `monitor`: If logs are available, a link to the [logs endpoint](#tag/Batch-Jobs/operation/debug-job).\n2. `result`: If batch job results are available, a link to the [results endpoint](#tag/Batch-Jobs/operation/list-results).\n\nThe relation types `monitor` and `result` may occur for various batch job states:\n\n1. `created`: When the batch job was executed before and has been reset to `created` after an\n [update](#tag/Batch-Jobs/operation/update-job) there could still be results and logs available\n until they get discarded by [queueing the batch job again](#tag/Batch-Jobs/operation/start-job).\n2. `finished`: The full log and results are expected to be available.\n3. `error` / `canceled`: Partial results and logs may be available.\n\nFor more relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "rel": "result", - "type": "application/json", - "title": "Batch Job Results", - "href": "https://openeo.example/api/v1/jobs/123/logs" - }, - { - "rel": "result", - "type": "application/json", - "title": "Batch Job Logs", - "href": "https://openeo.example/api/v1/jobs/123/logs" - } - ] - } - } - }, - "job_id": { - "type": "string", - "description": "Per-backend unique identifier of the batch job, generated by the back-end during creation. MUST match the specified pattern.", - "pattern": "^[\\w\\-\\.~]+$", - "example": "a3cca2b2aa1e3b5b" - }, - "created": { - "type": "string", - "format": "date-time", - "description": "Date and time of creation, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2017-01-01T09:32:12Z" - }, - "updated": { - "type": "string", - "format": "date-time", - "description": "Date and time of the last status change, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2017-01-01T09:36:18Z" - }, - "description": { - "type": "string", - "format": "commonmark", - "description": "Detailed description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation." - }, - "object_title": { - "type": "string", - "description": "A human-readable short title to be displayed to users **in addition** to the names specified in the keys. This property is only for better user experience so that users can understand the names better. Example titles could be `GeoTiff` for the key `GTiff` (for file formats) or `OGC Web Map Service` for the key `WMS` (for service types). The title MUST NOT be used in communication (e.g. in process graphs), although clients MAY translate the titles into the corresponding names." - }, - "eo_title": { - "description": "A short description to easily distinguish entities.", - "type": "string", - "nullable": true, - "example": "NDVI based on Sentinel 2" - }, - "eo_description": { - "type": "string", - "format": "commonmark", - "description": "Detailed multi-line description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation.", - "nullable": true, - "example": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2" - }, - "process_description": { - "type": "string", - "format": "commonmark", - "description": "Detailed description to explain the entity.\n\n[CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. In addition to the CommonMark syntax, clients can convert process IDs that are formatted as in the following example into links instead of code blocks: ``` ``process_id()`` ```" - }, - "service": { - "title": "Secondary Web Service", - "description": "The metadata of a secondary web service that has been submitted by the authenticated user.", - "type": "object", - "required": [ - "id", - "enabled", - "type", - "url" - ], - "properties": { - "id": { - "$ref": "#/components/schemas/service_id" - }, - "title": { - "$ref": "#/components/schemas/eo_title" - }, - "description": { - "$ref": "#/components/schemas/eo_description" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL at which the secondary web service is accessible. Doesn't necessarily need to be located within the API.", - "example": "https://openeo.example/wms/wms-a3cca9" - }, - "type": { - "$ref": "#/components/schemas/service_type" - }, - "enabled": { - "$ref": "#/components/schemas/service_enabled" - }, - "process": { - "$ref": "#/components/schemas/process_graph_with_metadata" - }, - "configuration": { - "$ref": "#/components/schemas/service_configuration" - }, - "attributes": { - "title": "Secondary Web Service Attributes", - "type": "object", - "description": "Additional attributes of the secondary web service, e.g. available layers for a WMS based on the bands in the underlying GeoTiff.", - "example": { - "layers": [ - "ndvi", - "evi" - ] - } - }, - "created": { - "$ref": "#/components/schemas/created" - }, - "plan": { - "$ref": "#/components/schemas/billing_plan" - }, - "costs": { - "$ref": "#/components/schemas/money" - }, - "budget": { - "$ref": "#/components/schemas/budget" - }, - "usage": { - "description": "Metrics about the resource usage of the secondary web service.\n\nBack-ends are not expected to update the metrics in real-time.\nFor detailed usage metrics for individual processing steps, metrics\ncan be added to the logs (e.g. `GET /jobs/{job_id}/logs`) with the\nsame schema.", - "allOf": [ - { - "$ref": "#/components/schemas/usage" - } - ] - }, - "log_level": { - "$ref": "#/components/schemas/min_log_level_default" - } - } - }, - "service_type": { - "description": "Definition of the service type to access result data. All available service types can be retrieved via `GET /service_types`. Service types MUST be accepted in a *case insensitive* manner.", - "type": "string", - "example": "wms" - }, - "service_configuration": { - "type": "object", - "title": "Service Configuration", - "description": "Map of configuration settings, i.e. the setting names supported by the secondary web service combined with actual values. See `GET /service_types` for supported configuration settings. For example, this could specify the required version of the service, visualization details or any other service dependant configuration.", - "example": { - "version": "1.3.0" - } - }, - "service_enabled": { - "type": "boolean", - "description": "Describes whether a secondary web service is responding to requests (true) or not (false). Disabled services don't produce any costs." - }, - "service_id": { - "type": "string", - "description": "A per-backend unique identifier of the secondary web service, generated by the back-end during creation. MUST match the specified pattern.", - "pattern": "^[\\w\\-\\.~]+$", - "example": "wms-a3cca9" - }, - "resource_parameter": { - "x-additionalPropertiesName": "Parameter Name", - "type": "object", - "title": "Resource Parameter", - "description": "Describes a parameter for various resources (e.g. file formats, service types).\n\nThe parameters are specified according to the [JSON Schema draft-07](http://json-schema.org/) specification.\nSee the chapter ['Schemas' in 'Defining Processes'](#section/Processes/Defining-Processes) for more information.\n\nThe following more complex JSON Schema keywords SHOULD NOT be used:\n`if`, `then`, `else`, `readOnly`, `writeOnly`, `dependencies`, `minProperties`, `maxProperties`, `patternProperties`.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved). This allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema is only a common subset of JSON Schema. Additional keywords MAY be used.", - "required": [ - "description" - ], - "properties": { - "description": { - "type": "string", - "description": "A brief description of the parameter according to [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.10.1)." - }, - "required": { - "type": "boolean", - "description": "Determines whether this parameter is mandatory.", - "default": false - }, - "experimental": { - "$ref": "#/components/schemas/experimental" - }, - "default": { - "description": "The default value represents what would be assumed by the consumer of the input as the value of the parameter if none is provided. The value MUST conform to the defined type for the parameter defined at the same level. For example, if type is string, then default can be \"foo\" but cannot be 1. See [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.10.2)." - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/process_json_schema" - } - ] - }, - "error": { - "title": "General Error", - "description": "An error object declares additional information about a client-side or server-side error.\nSee also: * [Error Handling](#section/API-Principles/Error-Handling) in the API in general. * [Common Error Codes](errors.json)", - "type": "object", - "required": [ - "code", - "message" - ], - "properties": { - "id": { - "type": "string", - "description": "A back-end MAY add a unique identifier to the error response to be able to log and track errors with further non-disclosable details. A client could communicate this id to a back-end provider to get further information.", - "example": "550e8400-e29b-11d4-a716-446655440000" - }, - "code": { - "$ref": "#/components/schemas/log_code" - }, - "message": { - "type": "string", - "description": "A message explaining what the client may need to change or what difficulties the server is facing.", - "example": "Parameter 'sample' is missing." - }, - "links": { - "$ref": "#/components/schemas/log_links" - } - } - }, - "log_code": { - "type": "string", - "description": "The code is either one of the standardized error codes or a custom code, for example specified by a user in the `inspect` process.", - "example": "SampleError" - }, - "log_links": { - "description": "Links related to this log entry / error, e.g. to a resource that\nprovides further explanations.\n\nFor relation types see the lists of\n[common relation types in openEO](#section/API-Principles/Web-Linking).", - "type": "array", - "items": { - "$ref": "#/components/schemas/link" - }, - "example": [ - { - "href": "https://openeo.example/docs/errors/SampleError", - "rel": "about" - } - ] - }, - "log_level": { - "description": "The severity level of the log entry.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\n\nThe level `error` usually corresponds with critical issues that usually terminate the data processing.", - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "example": "error" - }, - "min_log_level_default": { - "description": "The minimum severity level for log entries that the back-end stores for the processing request.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the back-end will only store log entries with the level `warning` and `error`.\n\nThe default minimum log level is `info`. Users need to specifically set this property to `debug` to get *all* log entries.\nIt is RECOMMENDED that users set the level at least to \"warning\" in production workflows.", - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "default": "info", - "example": "warning" - }, - "min_log_level_update": { - "description": "Updates the minimum severity level for log entries that the back-end stores for the processing requests.\n\nThe back-end doesn't need to update existing log entries.", - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "example": "warning" - }, - "data_type_schema": { - "title": "Data Types", - "description": "Either a single data type or a list of data types.", - "oneOf": [ - { - "$ref": "#/components/schemas/process_json_schema" - }, - { - "title": "Multiple data types", - "description": "A list of data types this parameter supports, specified as JSON Schemas.", - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/process_json_schema" - } - } - ] - }, - "process_schema": { - "title": "Process Data types", - "description": "Either a single data type or a list of data types for process parameter or process return values.", - "oneOf": [ - { - "$ref": "#/components/schemas/process_json_schema" - }, - { - "title": "Multiple data types", - "description": "A list of data types supported, specified as JSON Schemas.", - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/process_json_schema" - } - } - ] - }, - "process_json_schema": { - "type": "object", - "title": "Single Data Type", - "description": "Specifies a data type supported by a parameter or return value.\n\nThe data types are specified according to the [JSON Schema draft-07](http://json-schema.org/) specification.\nSee the chapter ['Schemas' in 'Defining Processes'](#section/Processes/Defining-Processes) for more information.\n\nJSON Schemas SHOULD NOT contain `default`, `anyOf`, `oneOf`, `allOf` or `not` at the top-level of the schema.\nInstead specify each data type in a separate array element.\n\nThe following more complex JSON Schema keywords SHOULD NOT be used:\n`if`, `then`, `else`, `readOnly`, `writeOnly`, `dependencies`, `minProperties`, `maxProperties`, `patternProperties`.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved). This allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema is only a common subset of JSON Schema. Additional keywords MAY be used.", - "properties": { - "subtype": { - "type": "string", - "description": "The allowed sub data type for a value. See the chapter on [subtypes](#section/Processes/Defining-Processes) for more information." - }, - "deprecated": { - "$ref": "#/components/schemas/deprecated" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/json_schema" - } - ], - "oneOf": [ - { - "title": "Generic" - }, - { - "$ref": "#/components/schemas/process_graph_json_schema" - }, - { - "$ref": "#/components/schemas/datacube_json_schema" - } - ] - }, - "process_graph_json_schema": { - "title": "Process Graph", - "type": "object", - "properties": { - "subtype": { - "type": "string", - "enum": [ - "process-graph" - ] - }, - "parameters": { - "type": "array", - "title": "Process Graph Parameters", - "description": "A list of parameters passed to the child process graph.\n\nThe order in the array corresponds to the parameter order to\nbe used in clients that don't support named parameters.", - "items": { - "$ref": "#/components/schemas/parameter" - } - }, - "returns": { - "type": "object", - "title": "Process Graph Return Value", - "description": "Description of the data that is returned by the child process graph.", - "required": [ - "schema" - ], - "properties": { - "description": { - "$ref": "#/components/schemas/process_description" - }, - "schema": { - "$ref": "#/components/schemas/data_type_schema" - } - }, - "allOf": [ - { - "$ref": "#/components/schemas/process_json_schema" - } - ] - } - } - }, - "datacube_json_schema": { - "title": "Datacube", - "properties": { - "subtype": { - "type": "string", - "enum": [ - "datacube" - ] - }, - "dimensions": { - "title": "Datacube constraints", - "description": "Allows to specify requirements the data cube has to fulfill.\nRight now, it only allows to specify the dimension types and \nadds for specific dimension types:\n* axes for `spatial` dimensions in raster datacubes\n* geometry types for `geometry` dimensions in vector datacubes", - "type": "array", - "items": { - "type": "object", - "required": [ - "type" - ], - "oneOf": [ - { - "title": "Spatial (raster)", - "properties": { - "type": { - "type": "string", - "enum": [ - "spatial" - ] - }, - "axis": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/dimension_axis_xyz" - } - } - } - }, - { - "title": "Spatial (vector)", - "properties": { - "type": { - "type": "string", - "enum": [ - "geometry" - ] - }, - "geometry_type": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/geometry_type" - } - } - } - }, - { - "title": "Other", - "properties": { - "type": { - "type": "string", - "enum": [ - "bands", - "temporal", - "other" - ] - } - } - } - ] - } - } - } - }, - "json_schema": { - "type": "object", - "title": "JSON Schema", - "description": "A JSON Schema compliant to [JSON Schema draft-07](https://json-schema.org/draft-07/json-schema-validation.html) or later.\n\nJSON Schemas SHOULD always be dereferenced (i.e. all `$refs` should be resolved).\nThis allows clients to consume the schemas much better.\nClients are not expected to support dereferencing `$refs`.\n\nNote: The specified schema in the OpenAPI document is only a common subset of JSON Schema.\nAdditional keywords from the JSON Schema specification MAY be used.", - "properties": { - "$schema": { - "description": "The JSON Schema version. If not given in the context of openEO,\ndefaults to `draft-07`.\n\nYou may need to add the default value for `$schema` property explicitly to the JSON Schema\nobject before passing it to a JSON Schema validator.", - "type": "string", - "format": "uri", - "default": "http://json-schema.org/draft-07/schema#" - }, - "$id": { - "description": "ID of your JSON Schema.", - "type": "string", - "format": "uri" - }, - "type": { - "description": "The allowed basic data type(s) for a value.\n\nIf this property is not present, all data types are allowed.", - "oneOf": [ - { - "$ref": "#/components/schemas/json_schema_type" - }, - { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { - "$ref": "#/components/schemas/json_schema_type" - } - } - ] - }, - "pattern": { - "type": "string", - "format": "regex", - "description": "The regular expression a string value must match against." - }, - "enum": { - "type": "array", - "items": {}, - "description": "An exclusive list of allowed values." - }, - "minimum": { - "type": "number", - "description": "The minimum value (inclusive) allowed for a numerical value." - }, - "maximum": { - "type": "number", - "description": "The maximum value (inclusive) allowed for a numerical value." - }, - "minItems": { - "type": "number", - "minimum": 0, - "default": 0, - "description": "The minimum number of items required in an array." - }, - "maxItems": { - "type": "number", - "minimum": 0, - "description": "The maximum number of items required in an array." - }, - "items": { - "description": "Specifies schemas for the items in an array.", - "anyOf": [ - { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/json_schema" - } - }, - { - "$ref": "#/components/schemas/json_schema" - } - ] - } - }, - "additionalProperties": { - "description": "You can add any other property supported by the JSON Schema version that is given through the property `$schema`, so either [draft-07](https://json-schema.org/draft-07/json-schema-validation.html) or any later version." - } - }, - "json_schema_type": { - "type": "string", - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "file": { - "title": "Workspace File", - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string", - "description": "Path of the file, relative to the root directory of the user's server-side workspace.\nMUST NOT start with a slash `/` and MUST NOT be url-encoded.\n\nThe Windows-style path name component separator `\\` is not supported,\nalways use `/` instead.\n\nNote: The pattern only specifies a minimal subset of invalid characters.\nThe back-ends MAY enforce additional restrictions depending on their OS/environment.", - "example": "folder/file.txt", - "pattern": "^[^/\r\n\\:'\"][^\r\n\\:'\"]*$" - }, - "size": { - "type": "integer", - "description": "File size in bytes.", - "example": 1024 - }, - "modified": { - "type": "string", - "format": "date-time", - "description": "Date and time the file has lastly been modified, formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time.", - "example": "2018-01-03T10:55:29Z" - } - } - }, - "geometry_type": { - "title": "Geometry type", - "type": "string", - "enum": [ - "Point", - "MultiPoint", - "LineString", - "MultiLineString", - "Polygon", - "MultiPolygon", - "GeometryCollection" - ] - }, - "GeoJsonPoint3D": { - "type": "array", - "description": "Point in 3D space", - "minItems": 2, - "maxItems": 3, - "items": { - "type": "number" - } - }, - "GeoJsonPoint": { - "type": "object", - "title": "GeoJSON Point", - "required": [ - "type", - "coordinates" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "Point" - ] - }, - "coordinates": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - }, - "GeoJsonFeatureCollection": { - "type": "object", - "required": [ - "type", - "features" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "FeatureCollection" - ] - }, - "features": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonFeature" - } - } - } - }, - "GeoJsonFeature": { - "type": "object", - "required": [ - "type", - "geometry", - "properties" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "Feature" - ] - }, - "geometry": { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - "properties": { - "type": "object", - "nullable": true - } - } - }, - "GeoJson": { - "title": "GeoJSON", - "oneOf": [ - { - "$ref": "#/components/schemas/GeoJsonFeatureCollection" - }, - { - "$ref": "#/components/schemas/GeoJsonFeature" - }, - { - "$ref": "#/components/schemas/GeoJsonGeometry" - } - ] - }, - "GeoJsonGeometry": { - "title": "GeoJSON Geometry", - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "$ref": "#/components/schemas/geometry_type" - } - }, - "discriminator": { - "propertyName": "type", - "mapping": { - "Point": "#/components/schemas/GeoJsonPoint", - "LineString": "#/components/schemas/GeoJsonLineString", - "Polygon": "#/components/schemas/GeoJsonPolygon", - "MultiPoint": "#/components/schemas/GeoJsonMultiPoint", - "MultiLineString": "#/components/schemas/GeoJsonMultiLineString", - "MultiPolygon": "#/components/schemas/GeoJsonMultiPolygon", - "GeometryCollection": "#/components/schemas/GeoJsonGeometryCollection" - } - } - }, - "GeoJsonLineString": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON LineString", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - ] - }, - "GeoJsonPolygon": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON Polygon", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - } - ] - }, - "GeoJsonMultiPoint": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON MultiPoint", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - ] - }, - "GeoJsonMultiLineString": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON MultiLineString", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - } - ] - }, - "GeoJsonMultiPolygon": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON MultiPolygon", - "required": [ - "coordinates" - ], - "properties": { - "coordinates": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonPoint3D" - } - } - } - } - } - } - ] - }, - "GeoJsonGeometryCollection": { - "allOf": [ - { - "$ref": "#/components/schemas/GeoJsonGeometry" - }, - { - "type": "object", - "title": "GeoJSON GeometryCollection", - "required": [ - "geometries" - ], - "properties": { - "geometries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GeoJsonGeometry" - } - } - } - } - ] - }, - "log_entry": { - "title": "Log Entry", - "description": "An log message that communicates information about the processed data.", - "type": "object", - "required": [ - "id", - "level", - "message" - ], - "properties": { - "id": { - "type": "string", - "description": "An unique identifier for the log message, could simply be an incrementing number.", - "example": "1" - }, - "code": { - "$ref": "#/components/schemas/log_code" - }, - "level": { - "$ref": "#/components/schemas/log_level" - }, - "message": { - "type": "string", - "description": "A concise message explaining the log entry.\nMessages do *not* explicitly support [CommonMark 0.29](http://commonmark.org/) syntax as other descriptive fields in the openEO API do, but the messages MAY contain line breaks or indentation.\nIt is NOT RECOMMENDED to add stacktraces to the `message`.", - "example": "Can't load the UDF file from the URL `https://openeo.example/invalid/file.txt`. Server responded with error 404." - }, - "time": { - "type": "string", - "format": "date-time", - "title": "Date and Time", - "description": "The date and time the event happened, in UTC. Formatted as a [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) date-time." - }, - "data": { - "description": "Data of any type. It is the back-ends task to decide how to best\npresent passed data to a user.\n\nFor example, a datacube passed to the `inspect` SHOULD return the\nmetadata similar to the collection metadata, including `cube:dimensions`.\nThere are implementation guidelines available for the `inspect` process." - }, - "path": { - "description": "Describes where the log entry originates from.\n\nThe first element of the array is the process that has triggered the log entry, the second element is the parent of the process that has triggered the log entry, etc. This pattern is followed until the root of the process graph.", - "type": "array", - "items": { - "type": "object", - "required": [ - "node_id" - ], - "properties": { - "node_id": { - "type": "string", - "description": "The id of the node the log entry originates from.", - "example": "runudf1" - }, - "process_id": { - "$ref": "#/components/schemas/process_id" - }, - "namespace": { - "$ref": "#/components/schemas/process_namespace" - }, - "parameter": { - "type": "string", - "description": "If applicable, the name of the parameter the log entry corresponds to.", - "pattern": "^\\w+$", - "nullable": true, - "example": "udf" - } - } - } - }, - "usage": { - "$ref": "#/components/schemas/usage" - }, - "links": { - "$ref": "#/components/schemas/log_links" - } - } - }, - "usage": { - "title": "Resource usage metrics", - "type": "object", - "properties": { - "cpu": { - "description": "Specifies the CPU usage, usually in a unit such as `cpu-seconds`.", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "memory": { - "description": "Specifies the memory usage, usually in a unit such as `mb-seconds` or `gb-hours`.", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "duration": { - "description": "Specifies the wall time, usually in a unit such as `seconds`, `minutes` or `hours`.", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "network": { - "description": "Specifies the network transfer usage (incoming and outgoing), usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "disk": { - "description": "Specifies the amount of input (read) and output (write) operations on the storage such as disks, usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "storage": { - "description": "Specifies the usage of storage space, usually in a unit such as `b` (bytes), `kb` (kilobytes), `mb` (megabytes) or `gb` (gigabytes).", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - } - }, - "additionalProperties": { - "description": "Additional metrics.", - "allOf": [ - { - "$ref": "#/components/schemas/usage_metric" - } - ] - }, - "example": { - "cpu": { - "value": 40668, - "unit": "cpu-seconds" - }, - "duration": { - "value": 2611, - "unit": "seconds" - }, - "memory": { - "value": 108138811, - "unit": "mb-seconds" - }, - "network": { - "value": 0, - "unit": "kb" - }, - "storage": { - "value": 55, - "unit": "mb" - } - } - }, - "usage_metric": { - "type": "object", - "required": [ - "value", - "unit" - ], - "properties": { - "value": { - "type": "number", - "minimum": 0 - }, - "unit": { - "type": "string" - } - } - } - }, - "responses": { - "logs": { - "description": "Lists the requested log entries.", - "content": { - "application/json": { - "schema": { - "title": "Log Entries", - "type": "object", - "required": [ - "logs", - "links" - ], - "properties": { - "level": { - "description": "The minimum severity level for log entries that the back-end returns.\nThis property MUST reflect the effective lowest `level` that may appear in the document,\nwhich is (if implemented) the highest level of:\n1. the `log_level` specified by the user for the processing request.\n2. the `level` specified by the user for the log request.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the logs will only contain entries with the level `warning` and `error`.", - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "default": "debug" - }, - "logs": { - "description": "A chronological list of logs.", - "type": "array", - "items": { - "$ref": "#/components/schemas/log_entry" - } - }, - "links": { - "$ref": "#/components/schemas/links_pagination" - } - } - } - } - } - }, - "client_error": { - "description": "The request can't be fulfilled due to an error on client-side, i.e. the\nrequest is invalid. The client SHOULD NOT repeat the request without\nmodifications.\n\nThe response body SHOULD contain a JSON error object.\nMUST be any HTTP status code specified in [RFC\n7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6). This request\nusually does not respond with HTTP status codes 401 and 403 due to\nmissing authorization. HTTP status code 404 SHOULD be used if the value\nof a path parameter is invalid.\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/error" - } - } - } - }, - "client_error_auth": { - "description": "The request can't be fulfilled due to an error on client-side, i.e. the\nrequest is invalid. The client SHOULD NOT repeat the request without\nmodifications.\n\nThe response body SHOULD contain a JSON error object.\nMUST be any HTTP status code specified in [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6).\nThis request MUST respond with HTTP status codes 401 if authorization is required or\n403 if the authorization failed or access is forbidden in general to the\nauthenticated user. HTTP status code 404 SHOULD be used if the value of\na path parameter is invalid.\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/error" - } - } - } - }, - "server_error": { - "description": "The request can't be fulfilled due to an error at the back-end. The\nerror is never the client’s fault and therefore it is reasonable for the\nclient to retry the exact same request that triggered this response.\n\nThe response body SHOULD contain a JSON error object. MUST be any HTTP\nstatus code specified in [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231.html#section-6.6).\n\nSee also:\n* [Error Handling](#section/API-Principles/Error-Handling) in the API in general.\n* [Common Error Codes](errors.json)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/error" - } - } - } - } - }, - "parameters": { - "pagination_limit": { - "name": "limit", - "description": "This parameter enables pagination for the endpoint and specifies the maximum number of\nelements that arrays in the top-level object (e.g. collections, processes, batch jobs,\nsecondary services, log entries, etc.) are allowed to contain.\nThe `links` array MUST NOT be paginated like the resources,\nbut instead contain links related to the paginated resources\nor the pagination itself (e.g. a link to the next page).\nIf the parameter is not provided or empty, all elements are returned.\n\nPagination is OPTIONAL: back-ends or clients may not support it.\nTherefore it MUST be implemented in a way that clients not supporting\npagination get all resources regardless. Back-ends not supporting\npagination MUST return all resources.\n\nIf the response is paginated, the `links` array MUST be used to communicate the\nlinks for browsing the pagination with predefined `rel` types. See the `links` array schema\nfor supported `rel` types.\nBack-end implementations can, unless specified otherwise, use all kind of pagination techniques,\ndepending on what is supported best by their infrastructure: page-based, offset-based, token-based\nor something else. The clients SHOULD use whatever is specified\nin the links with the corresponding `rel` types.", - "in": "query", - "allowEmptyValue": true, - "example": 10, - "schema": { - "type": "integer", - "minimum": 1 - } - }, - "log_offset": { - "name": "offset", - "description": "The last identifier (property `id` of a log entry) the client has received. If provided, the back-ends only sends the entries that occurred after the specified identifier. If not provided or empty, start with the first entry.", - "in": "query", - "allowEmptyValue": true, - "example": "log1234", - "schema": { - "type": "string" - } - }, - "log_level": { - "name": "level", - "description": "The minimum severity level for log entries that the back-end returns.\n\nThe order of the levels is as follows (from low to high severity): `debug`, `info`, `warning`, `error`.\nThat means if `warning` is set, the back-end will only return log entries with the level `warning` and `error`.\n\nThe default minimum log level is `debug`, which returns all log levels.", - "in": "query", - "allowEmptyValue": true, - "example": "error", - "schema": { - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ], - "default": "info" - } - }, - "service_id": { - "name": "service_id", - "in": "path", - "description": "Identifier of the secondary web service.", - "required": true, - "schema": { - "$ref": "#/components/schemas/service_id" - } - }, - "job_id": { - "name": "job_id", - "in": "path", - "description": "Identifier of the batch job.", - "required": true, - "schema": { - "$ref": "#/components/schemas/job_id" - } - }, - "collection_id": { - "name": "collection_id", - "in": "path", - "description": "Collection identifier", - "required": true, - "schema": { - "$ref": "#/components/schemas/collection_id" - } - } - }, - "examples": { - "evi_user_defined_process": { - "description": "A user-defined process that computes the EVI.", - "value": { - "id": "evi", - "summary": "Enhanced Vegetation Index", - "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", - "parameters": [ - { - "name": "red", - "description": "Value from the red band.", - "schema": { - "type": "number" - } - }, - { - "name": "blue", - "description": "Value from the blue band.", - "schema": { - "type": "number" - } - }, - { - "name": "nir", - "description": "Value from the near infrared band.", - "schema": { - "type": "number" - } - } - ], - "returns": { - "description": "Computed EVI.", - "schema": { - "type": "number" - } - }, - "process_graph": { - "sub": { - "process_id": "subtract", - "arguments": { - "x": { - "from_parameter": "nir" - }, - "y": { - "from_parameter": "red" - } - } - }, - "p1": { - "process_id": "multiply", - "arguments": { - "x": 6, - "y": { - "from_parameter": "red" - } - } - }, - "p2": { - "process_id": "multiply", - "arguments": { - "x": -7.5, - "y": { - "from_parameter": "blue" - } - } - }, - "sum": { - "process_id": "sum", - "arguments": { - "data": [ - 1, - { - "from_parameter": "nir" - }, - { - "from_node": "p1" - }, - { - "from_node": "p2" - } - ] - } - }, - "div": { - "process_id": "divide", - "arguments": { - "x": { - "from_node": "sub" - }, - "y": { - "from_node": "sum" - } - } - }, - "p3": { - "process_id": "multiply", - "arguments": { - "x": 2.5, - "y": { - "from_node": "div" - } - }, - "result": true - } - } - } - } - }, - "securitySchemes": { - "Bearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "The Bearer Token MUST consist of the authentication method, a provider ID (if available) and the token itself. All separated by a forward slash `/`. Examples (replace `TOKEN` with the actual access token): (1) Basic authentication (no provider ID available): `basic//TOKEN` (2) OpenID Connect (provider ID is `ms`): `oidc/ms/TOKEN`. For OpenID Connect, the provider ID corresponds to the value specified for `id` for each provider in `GET /credentials/oidc`." - }, - "Basic": { - "type": "http", - "scheme": "basic" - } - } - } - } \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/openeo-api b/src/openeo_test_suite/tests/general/openeo-api new file mode 160000 index 0000000..c5a45b4 --- /dev/null +++ b/src/openeo_test_suite/tests/general/openeo-api @@ -0,0 +1 @@ +Subproject commit c5a45b4647b06e313a4f099e9119bfa3cca5c6a3 diff --git a/src/openeo_test_suite/tests/general/test_compliance.py b/src/openeo_test_suite/tests/general/test_compliance.py index 47f3e06..3dcea6d 100644 --- a/src/openeo_test_suite/tests/general/test_compliance.py +++ b/src/openeo_test_suite/tests/general/test_compliance.py @@ -1,7 +1,7 @@ from openapi_core import Spec import pytest import requests -import openeo_test_suite.tests.general.compliance_util as conformance_util +import openeo_test_suite.lib.compliance_util as conformance_util import uuid @@ -20,8 +20,8 @@ def domain(request): @pytest.fixture(scope="session") def spec(request): - return conformance_util.adjust_spec_json( - conformance_util.get_spec_path_json(), + return conformance_util.adjust_spec( + conformance_util.get_spec_path(), conformance_util.get_base_url(request), conformance_util.get_domain(request), ) @@ -265,12 +265,6 @@ def test_GET_me(base_url: str, spec: Spec, bearer_token: str): assert fail_log == "" -def test_GET_collections_collection_id_queryables( - base_url: str, spec: Spec, bearer_token: str -): - raise NotImplementedError() - - def test_GET_process_graphs(base_url: str, spec: Spec, bearer_token: str): """ setup: submit valid user defined processes From c25de6493c28936cfaf2c689d3698f95f24d48c4 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Tue, 6 Feb 2024 14:23:01 +0100 Subject: [PATCH 05/12] remove pytest.ini and add it to gitignore --- .gitignore | 1 + pytest.ini | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 pytest.ini diff --git a/.gitignore b/.gitignore index bb03491..cf08a46 100644 --- a/.gitignore +++ b/.gitignore @@ -172,3 +172,4 @@ pyrightconfig.json # vscode .vscode/ +pytest.ini diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index bac5362..0000000 --- a/pytest.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pytest] -addopts = -v --tb=short --openeo-backend-url=openeo.vito.be \ No newline at end of file From c61b93a0257fd802e34f61e58dbcffb22d7a5900 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Tue, 6 Feb 2024 16:06:23 +0100 Subject: [PATCH 06/12] renamed to evi --- .../put_process_graphs/put_process_graphs_1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openeo_test_suite/tests/general/payload_examples/put_process_graphs/put_process_graphs_1.json b/src/openeo_test_suite/tests/general/payload_examples/put_process_graphs/put_process_graphs_1.json index 9ded78e..d7a61f2 100644 --- a/src/openeo_test_suite/tests/general/payload_examples/put_process_graphs/put_process_graphs_1.json +++ b/src/openeo_test_suite/tests/general/payload_examples/put_process_graphs/put_process_graphs_1.json @@ -1,5 +1,5 @@ { - "id": "evil", + "id": "evi", "summary": "Enhanced Vegetation Index", "description": "Computes the Enhanced Vegetation Index (EVI). It is computed with the following formula: `2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)`.", "parameters": [ From 1f986b60dca7d4e0b90c3e47053d0115bc9c7ed2 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Wed, 7 Feb 2024 10:18:16 +0100 Subject: [PATCH 07/12] add longrunning mark to various tests, update old 1.1 examples to newer 1.2 examples --- src/openeo_test_suite/lib/compliance_util.py | 4 +- .../patch_jobs/patch_jobs_1.json | 570 ++++++++---------- .../post_result/post_result_1.json | 568 ++++++++--------- .../tests/general/test_compliance.py | 29 +- 4 files changed, 526 insertions(+), 645 deletions(-) diff --git a/src/openeo_test_suite/lib/compliance_util.py b/src/openeo_test_suite/lib/compliance_util.py index a4cf77b..3fcb262 100644 --- a/src/openeo_test_suite/lib/compliance_util.py +++ b/src/openeo_test_suite/lib/compliance_util.py @@ -16,7 +16,7 @@ from openapi_core import validate_response from openapi_core.contrib.requests import RequestsOpenAPIRequest from openapi_core.contrib.requests import RequestsOpenAPIResponse -from openapi_core import V30ResponseValidator +from openapi_core import V31ResponseValidator def test_endpoint( @@ -121,7 +121,7 @@ def test_endpoint( try: if check_status_code(expected_status_codes, openapi_response.status_code): validate_response( - openapi_request, openapi_response, spec=spec, cls=V30ResponseValidator + openapi_request, openapi_response, spec=spec, cls=V31ResponseValidator ) else: raise UnexpectedStatusCodeException( diff --git a/src/openeo_test_suite/tests/general/payload_examples/patch_jobs/patch_jobs_1.json b/src/openeo_test_suite/tests/general/payload_examples/patch_jobs/patch_jobs_1.json index 49883f0..60c0119 100644 --- a/src/openeo_test_suite/tests/general/payload_examples/patch_jobs/patch_jobs_1.json +++ b/src/openeo_test_suite/tests/general/payload_examples/patch_jobs/patch_jobs_1.json @@ -1,100 +1,18 @@ { - "title": "NDVI based on Sentinel 2", - "description": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2", - "process": { - "id": "ndvi", - "summary": "string", - "description": "string", - "parameters": [ - { - "schema": { - "parameters": [ - { - "schema": { - "type": "array", - "subtype": "string", - "pattern": "/regex/", - "enum": [ - null - ], - "minimum": 0, - "maximum": 0, - "minItems": 0, - "maxItems": 0, - "items": [ - {} - ], - "deprecated": false - }, - "name": "string", - "description": "string", - "optional": false, - "deprecated": false, - "experimental": false, - "default": null - } - ], - "returns": { - "description": "string", - "schema": { - "type": "array", - "subtype": "string", - "pattern": "/regex/", - "enum": [ - null - ], - "minimum": 0, - "maximum": 0, - "minItems": 0, - "maxItems": 0, - "items": [ - {} - ], - "deprecated": false - }, - "type": "array", - "subtype": "string", - "pattern": "/regex/", - "enum": [ - null - ], - "minimum": 0, - "maximum": 0, - "minItems": 0, - "maxItems": 0, - "items": [ - {} - ], - "deprecated": false - }, - "type": "array", - "subtype": "string", - "pattern": "/regex/", - "enum": [ - null - ], - "minimum": 0, - "maximum": 0, - "minItems": 0, - "maxItems": 0, - "items": [ - {} - ], - "deprecated": false - }, - "name": "string", - "description": "string", - "optional": false, - "deprecated": false, - "experimental": false, - "default": null - } - ], - "returns": { - "description": "string", + "title": "NDVI based on Sentinel 2", + "description": "Deriving minimum NDVI measurements over pixel time series of Sentinel 2", + "process": { + "id": "ndvi", + "summary": "string", + "description": "string", + "parameters": [ + { "schema": { - "type": "array", "subtype": "string", + "deprecated": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://example.com", + "type": "array", "pattern": "/regex/", "enum": [ null @@ -106,237 +24,269 @@ "items": [ {} ], - "deprecated": false - } + "property1": null, + "property2": null + }, + "name": "string", + "description": "string", + "optional": false, + "deprecated": false, + "experimental": false, + "default": null + } + ], + "returns": { + "description": "string", + "schema": { + "subtype": "string", + "deprecated": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://example.com", + "type": "array", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "property1": null, + "property2": null + } + }, + "categories": [ + "string" + ], + "deprecated": false, + "experimental": false, + "exceptions": { + "Error Code1": { + "description": "string", + "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", + "http": 400 }, - "categories": [ - "string" - ], - "deprecated": false, - "experimental": false, - "exceptions": { - "Error Code1": { - "description": "string", - "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", - "http": 400 + "Error Code2": { + "description": "string", + "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", + "http": 400 + } + }, + "examples": [ + { + "title": "string", + "description": "string", + "arguments": { + "property1": { + "from_parameter": null, + "from_node": null, + "process_graph": null + }, + "property2": { + "from_parameter": null, + "from_node": null, + "process_graph": null + } }, - "Error Code2": { - "description": "string", - "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", - "http": 400 + "returns": null + } + ], + "links": [ + { + "rel": "related", + "href": "https://openeo.example", + "type": "text/html", + "title": "openEO" + } + ], + "process_graph": { + "dc": { + "process_id": "load_collection", + "arguments": { + "id": "Sentinel-2", + "spatial_extent": { + "west": 16.1, + "east": 16.6, + "north": 48.6, + "south": 47.2 + }, + "temporal_extent": [ + "2018-01-01", + "2018-02-01" + ] } }, - "examples": [ - { - "title": "string", - "description": "string", - "arguments": { - "property1": { - "from_parameter": null, - "from_node": null, - "process_graph": null - }, - "property2": { - "from_parameter": null, - "from_node": null, - "process_graph": null - } + "bands": { + "process_id": "filter_bands", + "description": "Filter and order the bands. The order is important for the following reduce operation.", + "arguments": { + "data": { + "from_node": "dc" }, - "returns": null - } - ], - "links": [ - { - "rel": "related", - "href": "https://example.openeo.org", - "type": "text/html", - "title": "openEO" + "bands": [ + "B08", + "B04", + "B02" + ] } - ], - "process_graph": { - "dc": { - "process_id": "load_collection", - "arguments": { - "id": "Sentinel-2", - "spatial_extent": { - "west": 16.1, - "east": 16.6, - "north": 48.6, - "south": 47.2 - }, - "temporal_extent": [ - "2018-01-01", - "2018-02-01" - ] - } - }, - "bands": { - "process_id": "filter_bands", - "description": "Filter and order the bands. The order is important for the following reduce operation.", - "arguments": { - "data": { - "from_node": "dc" - }, - "bands": [ - "B08", - "B04", - "B02" - ] - } - }, - "evi": { - "process_id": "reduce", - "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", - "arguments": { - "data": { - "from_node": "bands" - }, - "dimension": "bands", - "reducer": { - "process_graph": { - "nir": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" + }, + "evi": { + "process_id": "reduce", + "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", + "arguments": { + "data": { + "from_node": "bands" + }, + "dimension": "bands", + "reducer": { + "process_graph": { + "nir": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 0 + } + }, + "red": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 1 + } + }, + "blue": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 2 + } + }, + "sub": { + "process_id": "subtract", + "arguments": { + "data": [ + { + "from_node": "nir" }, - "index": 0 - } - }, - "red": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" + { + "from_node": "red" + } + ] + } + }, + "p1": { + "process_id": "product", + "arguments": { + "data": [ + 6, + { + "from_node": "red" + } + ] + } + }, + "p2": { + "process_id": "product", + "arguments": { + "data": [ + -7.5, + { + "from_node": "blue" + } + ] + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_node": "nir" }, - "index": 1 - } - }, - "blue": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" + { + "from_node": "p1" }, - "index": 2 - } - }, - "sub": { - "process_id": "subtract", - "arguments": { - "data": [ - { - "from_node": "nir" - }, - { - "from_node": "red" - } - ] - } - }, - "p1": { - "process_id": "product", - "arguments": { - "data": [ - 6, - { - "from_node": "red" - } - ] - } - }, - "p2": { - "process_id": "product", - "arguments": { - "data": [ - -7.5, - { - "from_node": "blue" - } - ] - } - }, - "sum": { - "process_id": "sum", - "arguments": { - "data": [ - 1, - { - "from_node": "nir" - }, - { - "from_node": "p1" - }, - { - "from_node": "p2" - } - ] - } - }, - "div": { - "process_id": "divide", - "arguments": { - "data": [ - { - "from_node": "sub" - }, - { - "from_node": "sum" - } - ] - } - }, - "p3": { - "process_id": "product", - "arguments": { - "data": [ - 2.5, - { - "from_node": "div" - } - ] - }, - "result": true + { + "from_node": "p2" + } + ] } - } - } - } - }, - "mintime": { - "process_id": "reduce", - "description": "Compute a minimum time composite by reducing the temporal dimension", - "arguments": { - "data": { - "from_node": "evi" - }, - "dimension": "temporal", - "reducer": { - "process_graph": { - "min": { - "process_id": "min", - "arguments": { - "data": { - "from_parameter": "data" + }, + "div": { + "process_id": "divide", + "arguments": { + "data": [ + { + "from_node": "sub" + }, + { + "from_node": "sum" } - }, - "result": true + ] } + }, + "p3": { + "process_id": "product", + "arguments": { + "data": [ + 2.5, + { + "from_node": "div" + } + ] + }, + "result": true } } } - }, - "save": { - "process_id": "save_result", - "arguments": { - "data": { - "from_node": "mintime" - }, - "format": "GTiff" + } + }, + "mintime": { + "process_id": "reduce", + "description": "Compute a minimum time composite by reducing the temporal dimension", + "arguments": { + "data": { + "from_node": "evi" }, - "result": true + "dimension": "temporal", + "reducer": { + "process_graph": { + "min": { + "process_id": "min", + "arguments": { + "data": { + "from_parameter": "data" + } + }, + "result": true + } + } + } } + }, + "save": { + "process_id": "save_result", + "arguments": { + "data": { + "from_node": "mintime" + }, + "format": "GTiff" + }, + "result": true } - }, - "plan": "free", - "budget": 100 - } \ No newline at end of file + } + }, + "plan": "free", + "budget": 100, + "log_level": "warning" +} \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/payload_examples/post_result/post_result_1.json b/src/openeo_test_suite/tests/general/payload_examples/post_result/post_result_1.json index e3f20ae..b2febe3 100644 --- a/src/openeo_test_suite/tests/general/payload_examples/post_result/post_result_1.json +++ b/src/openeo_test_suite/tests/general/payload_examples/post_result/post_result_1.json @@ -1,98 +1,16 @@ { - "process": { - "id": "ndvi", - "summary": "string", - "description": "string", - "parameters": [ - { - "schema": { - "parameters": [ - { - "schema": { - "type": "array", - "subtype": "string", - "pattern": "/regex/", - "enum": [ - null - ], - "minimum": 0, - "maximum": 0, - "minItems": 0, - "maxItems": 0, - "items": [ - {} - ], - "deprecated": false - }, - "name": "string", - "description": "string", - "optional": false, - "deprecated": false, - "experimental": false, - "default": null - } - ], - "returns": { - "description": "string", - "schema": { - "type": "array", - "subtype": "string", - "pattern": "/regex/", - "enum": [ - null - ], - "minimum": 0, - "maximum": 0, - "minItems": 0, - "maxItems": 0, - "items": [ - {} - ], - "deprecated": false - }, - "type": "array", - "subtype": "string", - "pattern": "/regex/", - "enum": [ - null - ], - "minimum": 0, - "maximum": 0, - "minItems": 0, - "maxItems": 0, - "items": [ - {} - ], - "deprecated": false - }, - "type": "array", - "subtype": "string", - "pattern": "/regex/", - "enum": [ - null - ], - "minimum": 0, - "maximum": 0, - "minItems": 0, - "maxItems": 0, - "items": [ - {} - ], - "deprecated": false - }, - "name": "string", - "description": "string", - "optional": false, - "deprecated": false, - "experimental": false, - "default": null - } - ], - "returns": { - "description": "string", + "process": { + "id": "ndvi", + "summary": "string", + "description": "string", + "parameters": [ + { "schema": { - "type": "array", "subtype": "string", + "deprecated": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://example.com", + "type": "array", "pattern": "/regex/", "enum": [ null @@ -104,237 +22,271 @@ "items": [ {} ], - "deprecated": false - } + "property1": null, + "property2": null + }, + "name": "string", + "description": "string", + "optional": false, + "deprecated": false, + "experimental": false, + "default": null + } + ], + "returns": { + "description": "string", + "schema": { + "subtype": "string", + "deprecated": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://example.com", + "type": "array", + "pattern": "/regex/", + "enum": [ + null + ], + "minimum": 0, + "maximum": 0, + "minItems": 0, + "maxItems": 0, + "items": [ + {} + ], + "property1": null, + "property2": null + } + }, + "categories": [ + "string" + ], + "deprecated": false, + "experimental": false, + "exceptions": { + "Error Code1": { + "description": "string", + "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", + "http": 400 }, - "categories": [ - "string" - ], - "deprecated": false, - "experimental": false, - "exceptions": { - "Error Code1": { - "description": "string", - "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", - "http": 400 + "Error Code2": { + "description": "string", + "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", + "http": 400 + } + }, + "examples": [ + { + "title": "string", + "description": "string", + "arguments": { + "property1": { + "from_parameter": null, + "from_node": null, + "process_graph": null + }, + "property2": { + "from_parameter": null, + "from_node": null, + "process_graph": null + } }, - "Error Code2": { - "description": "string", - "message": "The value specified for the process argument '{argument}' in process '{process}' is invalid: {reason}", - "http": 400 + "returns": null + } + ], + "links": [ + { + "rel": "related", + "href": "https://openeo.example", + "type": "text/html", + "title": "openEO" + } + ], + "process_graph": { + "dc": { + "process_id": "load_collection", + "arguments": { + "id": "Sentinel-2", + "spatial_extent": { + "west": 16.1, + "east": 16.6, + "north": 48.6, + "south": 47.2 + }, + "temporal_extent": [ + "2018-01-01", + "2018-02-01" + ] } }, - "examples": [ - { - "title": "string", - "description": "string", - "arguments": { - "property1": { - "from_parameter": null, - "from_node": null, - "process_graph": null - }, - "property2": { - "from_parameter": null, - "from_node": null, - "process_graph": null - } + "bands": { + "process_id": "filter_bands", + "description": "Filter and order the bands. The order is important for the following reduce operation.", + "arguments": { + "data": { + "from_node": "dc" }, - "returns": null - } - ], - "links": [ - { - "rel": "related", - "href": "https://example.openeo.org", - "type": "text/html", - "title": "openEO" + "bands": [ + "B08", + "B04", + "B02" + ] } - ], - "process_graph": { - "dc": { - "process_id": "load_collection", - "arguments": { - "id": "Sentinel-2", - "spatial_extent": { - "west": 16.1, - "east": 16.6, - "north": 48.6, - "south": 47.2 - }, - "temporal_extent": [ - "2018-01-01", - "2018-02-01" - ] - } - }, - "bands": { - "process_id": "filter_bands", - "description": "Filter and order the bands. The order is important for the following reduce operation.", - "arguments": { - "data": { - "from_node": "dc" - }, - "bands": [ - "B08", - "B04", - "B02" - ] - } - }, - "evi": { - "process_id": "reduce", - "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", - "arguments": { - "data": { - "from_node": "bands" - }, - "dimension": "bands", - "reducer": { - "process_graph": { - "nir": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" + }, + "evi": { + "process_id": "reduce", + "description": "Compute the EVI. Formula: 2.5 * (NIR - RED) / (1 + NIR + 6*RED + -7.5*BLUE)", + "arguments": { + "data": { + "from_node": "bands" + }, + "dimension": "bands", + "reducer": { + "process_graph": { + "nir": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 0 + } + }, + "red": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 1 + } + }, + "blue": { + "process_id": "array_element", + "arguments": { + "data": { + "from_parameter": "data" + }, + "index": 2 + } + }, + "sub": { + "process_id": "subtract", + "arguments": { + "data": [ + { + "from_node": "nir" }, - "index": 0 - } - }, - "red": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" + { + "from_node": "red" + } + ] + } + }, + "p1": { + "process_id": "product", + "arguments": { + "data": [ + 6, + { + "from_node": "red" + } + ] + } + }, + "p2": { + "process_id": "product", + "arguments": { + "data": [ + -7.5, + { + "from_node": "blue" + } + ] + } + }, + "sum": { + "process_id": "sum", + "arguments": { + "data": [ + 1, + { + "from_node": "nir" }, - "index": 1 - } - }, - "blue": { - "process_id": "array_element", - "arguments": { - "data": { - "from_parameter": "data" + { + "from_node": "p1" }, - "index": 2 - } - }, - "sub": { - "process_id": "subtract", - "arguments": { - "data": [ - { - "from_node": "nir" - }, - { - "from_node": "red" - } - ] - } - }, - "p1": { - "process_id": "product", - "arguments": { - "data": [ - 6, - { - "from_node": "red" - } - ] - } - }, - "p2": { - "process_id": "product", - "arguments": { - "data": [ - -7.5, - { - "from_node": "blue" - } - ] - } - }, - "sum": { - "process_id": "sum", - "arguments": { - "data": [ - 1, - { - "from_node": "nir" - }, - { - "from_node": "p1" - }, - { - "from_node": "p2" - } - ] - } - }, - "div": { - "process_id": "divide", - "arguments": { - "data": [ - { - "from_node": "sub" - }, - { - "from_node": "sum" - } - ] - } - }, - "p3": { - "process_id": "product", - "arguments": { - "data": [ - 2.5, - { - "from_node": "div" - } - ] - }, - "result": true + { + "from_node": "p2" + } + ] } - } - } - } - }, - "mintime": { - "process_id": "reduce", - "description": "Compute a minimum time composite by reducing the temporal dimension", - "arguments": { - "data": { - "from_node": "evi" - }, - "dimension": "temporal", - "reducer": { - "process_graph": { - "min": { - "process_id": "min", - "arguments": { - "data": { - "from_parameter": "data" + }, + "div": { + "process_id": "divide", + "arguments": { + "data": [ + { + "from_node": "sub" + }, + { + "from_node": "sum" } - }, - "result": true + ] } + }, + "p3": { + "process_id": "product", + "arguments": { + "data": [ + 2.5, + { + "from_node": "div" + } + ] + }, + "result": true } } } - }, - "save": { - "process_id": "save_result", - "arguments": { - "data": { - "from_node": "mintime" - }, - "format": "GTiff" + } + }, + "mintime": { + "process_id": "reduce", + "description": "Compute a minimum time composite by reducing the temporal dimension", + "arguments": { + "data": { + "from_node": "evi" }, - "result": true + "dimension": "temporal", + "reducer": { + "process_graph": { + "min": { + "process_id": "min", + "arguments": { + "data": { + "from_parameter": "data" + } + }, + "result": true + } + } + } } + }, + "save": { + "process_id": "save_result", + "arguments": { + "data": { + "from_node": "mintime" + }, + "format": "GTiff" + }, + "result": true } - }, - "budget": 100, - "plan": "free" - } \ No newline at end of file + } + }, + "budget": 100, + "plan": "free", + "log_level": "warning", + "property1": null, + "property2": null +} \ No newline at end of file diff --git a/src/openeo_test_suite/tests/general/test_compliance.py b/src/openeo_test_suite/tests/general/test_compliance.py index 3dcea6d..b424c71 100644 --- a/src/openeo_test_suite/tests/general/test_compliance.py +++ b/src/openeo_test_suite/tests/general/test_compliance.py @@ -5,9 +5,6 @@ import uuid -# region Test Fixtures - - @pytest.fixture(scope="session") def base_url(request): return conformance_util.get_base_url(request=request) @@ -33,11 +30,6 @@ def bearer_token(pytestconfig): return f"Bearer {bearer_token}" -# endregion - -# region Test Implementations - - def test_GET_backend_info(base_url: str, spec: Spec, bearer_token: str): """ tests all the generic GET endpoints that require neither setup nor cleanup @@ -689,9 +681,7 @@ def test_POST_jobs_job_id_results(base_url: str, spec: Spec, bearer_token: str): @pytest.mark.vv -@pytest.mark.skip( - reason="Takes too long for normal test runs, this decorator can be removed when fully testing is relevant" -) +@pytest.mark.longrunning def test_GET_jobs_job_id_results(base_url: str, spec: Spec, bearer_token: str): """ SETUP: POST jobs, START jobs (POST jobs/job_id/results), Wait for jobs to be finished @@ -869,9 +859,7 @@ def test_GET_jobs_job_id_logs(base_url: str, spec: Spec, bearer_token: str): assert fail_log == "" -@pytest.mark.skip( - reason="Takes too long for normal test runs, this decorator can be removed when fully testing is relevant" -) +@pytest.mark.longrunning def test_POST_result(base_url: str, spec: Spec, bearer_token: str): """ SETUP: gather payloads @@ -948,11 +936,6 @@ def test_POST_validation(base_url: str, spec: Spec, bearer_token: str): assert fail_log == "" -# endregion - -# region Negative Test Implementations - - def test_none_PUT_process_graphs_process_id( base_url: str, spec: Spec, bearer_token: str ): @@ -1226,9 +1209,7 @@ def test_negative_GET_jobs_job_id_logs(base_url: str, spec: Spec, bearer_token: assert fail_log == "" -@pytest.mark.skip( - reason="Takes too long for normal test runs, this decorator can be removed when fully testing is relevant" -) +@pytest.mark.longrunning def test_none_POST_result(base_url: str, spec: Spec, bearer_token: str): """ SETUP: gather payloads @@ -1411,9 +1392,7 @@ def test_empty_PATCH_jobs_job_id(base_url: str, spec: Spec, bearer_token: str): assert fail_log == "" -@pytest.mark.skip( - reason="Takes too long for normal test runs, this decorator can be removed when fully testing is relevant" -) +@pytest.mark.longrunning def test_empty_POST_result(base_url: str, spec: Spec, bearer_token: str): """ SETUP: gather payloads From bfde41593fa21b1dd35e9e2c7bbfd00eba7ec53b Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Wed, 7 Feb 2024 12:29:40 +0100 Subject: [PATCH 08/12] move submodule for openeo api to assets --- .gitmodules | 3 +++ {src/openeo_test_suite/tests/general => assets}/openeo-api | 0 2 files changed, 3 insertions(+) rename {src/openeo_test_suite/tests/general => assets}/openeo-api (100%) diff --git a/.gitmodules b/.gitmodules index 5d9e2ee..fd0b342 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ [submodule "src/openeo_test_suite/tests/general/openeo-api"] path = src/openeo_test_suite/tests/general/openeo-api url = git@github.com:Open-EO/openeo-api.git +[submodule "assets/openeo-api"] + path = assets/openeo-api + url = git@github.com:Open-EO/openeo-api.git diff --git a/src/openeo_test_suite/tests/general/openeo-api b/assets/openeo-api similarity index 100% rename from src/openeo_test_suite/tests/general/openeo-api rename to assets/openeo-api From 2a1fdfe0c666274eef9f367b1fbf1bb8d8d366c8 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Wed, 7 Feb 2024 13:15:57 +0100 Subject: [PATCH 09/12] Update README.md --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bba4a6d..ebbe2ea 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,17 @@ focussing on a specific API aspect to test or verify --html=reports/process-metadata.html ``` - **WP4 General openEO API compliance validation** (lead implementation partner: EODC) - - TODO: [Open-EO/openeo-test-suite#20](https://github.com/Open-EO/openeo-test-suite/issues/20) + - Main location: [`src/openeo_test_suite/tests/general`](./src/openeo_test_suite/tests/general) + - Provides tests to validate the general openEO API compliance of a back-end. + - The backend is checked against the openeo API specification defined in the [openeo-api](https://github.com/Open-EO/openeo-api/). + - There are some tests which might run for a long time (as they running process_graphs on the backends) these can be skippied by adding + `-m "not longrunning"` to the pytest command. + - Usage example of just running these tests against a desired openEO backend URL: + ```bash + pytest src/openeo_test_suite/tests/general \ + -U https://openeo.example \ + --html=reports/general.html + ``` - **WP5 Individual process testing** (lead implementation partner: M. Mohr) - Main location: [`src/openeo_test_suite/tests/processes/processing`](./src/openeo_test_suite/tests/processes/processing) - Provides tests to validate individual openEO processes, @@ -377,7 +387,7 @@ Some general guidelines: - Validation of process metadata: add new tests to `src/openeo_test_suite/tests/processes/metadata`. - General openEO API compliance validation: - - TODO: [Open-EO/openeo-test-suite#20](https://github.com/Open-EO/openeo-test-suite/issues/20) + add new tests to `src/openeo_test_suite/tests/general`. - Individual process testing: - new input-output pairs for existing or new processes: add them in the [openeo-processes](https://github.com/Open-EO/openeo-processes) project From 838e52347508df7487c864f616cc8fad4e6eca5e Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Wed, 7 Feb 2024 14:34:53 +0100 Subject: [PATCH 10/12] Removed git submodule from submodules file --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index fd0b342..5d89a1b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,9 +2,6 @@ path = assets/processes url = https://github.com/Open-EO/openeo-processes branch = add-tests -[submodule "src/openeo_test_suite/tests/general/openeo-api"] - path = src/openeo_test_suite/tests/general/openeo-api - url = git@github.com:Open-EO/openeo-api.git [submodule "assets/openeo-api"] path = assets/openeo-api url = git@github.com:Open-EO/openeo-api.git From 8311ba4af0b1b0b47f205d56c2cbdb5d58a2c883 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Wed, 7 Feb 2024 16:20:29 +0100 Subject: [PATCH 11/12] Update: replace print with logging, simplify wait_job_statuses function and test_endpoint function, replace getting filenames with glob, fix typehints, introduce validate_uri function, more robust get_spec_path and get_examples_path functions --- src/openeo_test_suite/lib/compliance_util.py | 196 +++++++------------ 1 file changed, 73 insertions(+), 123 deletions(-) diff --git a/src/openeo_test_suite/lib/compliance_util.py b/src/openeo_test_suite/lib/compliance_util.py index 3fcb262..9b2d2a7 100644 --- a/src/openeo_test_suite/lib/compliance_util.py +++ b/src/openeo_test_suite/lib/compliance_util.py @@ -1,3 +1,5 @@ +from pathlib import Path +import pathlib from typing import Union from openapi_core import Spec import yaml @@ -6,6 +8,8 @@ import uuid import requests import time +import logging +import openeo_test_suite from openeo_test_suite.lib.backend_under_test import ( get_backend_url, @@ -19,11 +23,16 @@ from openapi_core import V31ResponseValidator +from typing import Union +import requests +from requests import Request, Session + + def test_endpoint( base_url: str, endpoint_path: str, test_name: str, - spec: Spec, + spec: "Spec", payload: dict = None, bearer_token: str = None, method: str = "GET", @@ -31,92 +40,23 @@ def test_endpoint( return_response: bool = False, ): full_endpoint_url = f"{base_url}{endpoint_path}" + session = Session() + headers = {"Content-Type": "application/json"} if payload else {} - if bearer_token is not None: - if method == "POST": - requests_response = requests.post( - full_endpoint_url, - data=payload, - headers={ - "Content-Type": "application/json", - "Authorization": f"{bearer_token}", - }, - ) - - requests_request = requests.Request( - "post", - full_endpoint_url, - data=payload, - headers={ - "Content-Type": "application/json", - "Authorization": f"{bearer_token}", - }, - ) + if bearer_token: + headers["Authorization"] = bearer_token - elif method == "PUT": - requests_response = requests.put( - full_endpoint_url, - data=payload, - headers={ - "Content-Type": "application/json", - "Authorization": f"{bearer_token}", - }, - ) - - requests_request = requests.Request( - "put", - full_endpoint_url, - data=payload, - headers={ - "Content-Type": "application/json", - "Authorization": f"{bearer_token}", - }, - ) - - elif method == "PATCH": - requests_response = requests.patch( - full_endpoint_url, - data=payload, - headers={ - "Content-Type": "application/json", - "Authorization": f"{bearer_token}", - }, - ) - - requests_request = requests.Request( - "patch", - full_endpoint_url, - data=payload, - headers={ - "Content-Type": "application/json", - "Authorization": f"{bearer_token}", - }, - ) - - if method == "GET": - requests_response = requests.get( - full_endpoint_url, headers={"Authorization": f"{bearer_token}"} - ) - requests_request = requests.Request( - "get", full_endpoint_url, headers={"Authorization": f"{bearer_token}"} - ) - - elif method == "DELETE": - requests_response = requests.delete( - full_endpoint_url, headers={"Authorization": f"{bearer_token}"} - ) - requests_request = requests.Request( - "delete", - full_endpoint_url, - headers={"Authorization": f"{bearer_token}"}, - ) - # if both payload and bearer token are None, it can only be a simple get - else: - requests_response = requests.get(full_endpoint_url) - requests_request = requests.Request("get", full_endpoint_url) + response = session.request( + method=method.upper(), + url=full_endpoint_url, + json=payload, + headers=headers, + ) - openapi_request = RequestsOpenAPIRequest(requests_request) - openapi_response = RequestsOpenAPIResponse(requests_response) + openapi_request = RequestsOpenAPIRequest( + Request(method.upper(), full_endpoint_url, json=payload, headers=headers) + ) + openapi_response = RequestsOpenAPIResponse(response) try: if check_status_code(expected_status_codes, openapi_response.status_code): @@ -133,12 +73,12 @@ def test_endpoint( except Exception as e: print_test_results(e, endpoint_path=endpoint_path, test_name=test_name) if return_response: - return check_test_results(e), requests_response + return check_test_results(e), response else: return check_test_results(e) else: if return_response: - return "", requests_response + return "", response else: return "" @@ -184,23 +124,17 @@ def wait_job_statuses( """ end_time = time.time() + timeout while time.time() < end_time: - all_jobs_finished = True - for job_id in job_ids: - if all_jobs_finished: - all_jobs_finished = ( - get_batch_job_status( - base_url=base_url, bearer_token=bearer_token, job_id=job_id - ) - in job_statuses - ) - else: - break - if all_jobs_finished: - print("All jobs have reached their desired status.") - return True + if all( + get_batch_job_status( + base_url=base_url, bearer_token=bearer_token, job_id=job_id + ) + in job_statuses + for job_id in job_ids + ): + return True time.sleep(1) - print("Waiting on jobs to reach desired status..") - print("Jobs failed to reach desired state, timeout has been reached.") + logging.log("Waiting on jobs to reach desired status..") + logging.warn("Jobs failed to reach desired state, timeout has been reached.") return False @@ -305,7 +239,11 @@ def adjust_server_in_well_known(data, endpoint): def validate_uri(value): - return True + if not isinstance(value, str): + return False + if value.startswith("http://") or value.startswith("https://"): + return True + return False extra_format_validators = { @@ -328,25 +266,37 @@ def get_examples_path(): ) -def get_spec_path(): - return os.path.join( - os.getcwd(), "src/openeo_test_suite/tests/general/openeo-api/openapi.yaml" +def _guess_root(): + project_root = Path(openeo_test_suite.__file__).parents[2] + candidates = [ + project_root / "assets/openeo-api", + Path("./assets/openeo-api"), + Path("./openeo-test-suite/assets/openeo-api"), + ] + for candidate in candidates: + if candidate.exists() and candidate.is_dir(): + return candidate + raise ValueError( + f"Could not find valid processes test root directory (tried {candidates})" ) +def get_spec_path(): + return _guess_root() / "openapi.yaml" + + def load_payloads_from_directory(directory_path: str) -> list[dict]: - for filename in os.listdir(directory_path): - if filename.endswith(".json"): - file_path = os.path.join(directory_path, filename) - with open(file_path, "r") as file: - try: - # Load the JSON data from the file - data = json.load(file) - yield json.dumps(data) - except json.JSONDecodeError: - print(f"Error decoding JSON in file: {filename}") - except Exception as e: - print(f"Error reading file: {filename} - {str(e)}") + for filename in pathlib.Path.glob(directory_path, "*.json"): + file_path = os.path.join(directory_path, filename) + with open(file_path, "r") as file: + try: + # Load the JSON data from the file + data = json.load(file) + yield json.dumps(data) + except json.JSONDecodeError: + logging.error(f"Error decoding JSON in file: {filename}") + except Exception as e: + logging.error(f"Error reading file: {filename} - {str(e)}") def set_uuid_in_job(json_data): @@ -363,14 +313,14 @@ def set_uuid_in_job(json_data): def delete_id_resource( base_url: str, endpoint_path: str, bearer_token: str, ids: list[str] ): - try: - for id in ids: + for id in ids: + try: requests.delete( f"{base_url}/{endpoint_path}/{id}", headers={"Authorization": f"{bearer_token}"}, ) - except Exception as e: - print(e) + except Exception as e: + logging.error(f"Failed to delete resource with id {id}: {e}") def put_process_graphs(base_url: str, bearer_token: str): # TODO id and so forth @@ -395,7 +345,7 @@ def put_process_graphs(base_url: str, bearer_token: str): # TODO id and so fort }, ) except Exception as e: - print(e) + print(f"Failed to create process graph: {e}") return created_udp_ids From 11b37267ce409f05e6f8c50ee210602735580126 Mon Sep 17 00:00:00 2001 From: Gerald Walter Irsiegler Date: Wed, 7 Feb 2024 16:38:49 +0100 Subject: [PATCH 12/12] added clarification to adjust_spec function --- src/openeo_test_suite/lib/compliance_util.py | 37 +++++++++++--------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/openeo_test_suite/lib/compliance_util.py b/src/openeo_test_suite/lib/compliance_util.py index 9b2d2a7..5eab468 100644 --- a/src/openeo_test_suite/lib/compliance_util.py +++ b/src/openeo_test_suite/lib/compliance_util.py @@ -1,6 +1,6 @@ from pathlib import Path import pathlib -from typing import Union +from typing import Iterator, Union from openapi_core import Spec import yaml import json @@ -215,6 +215,13 @@ def check_test_results(e: Exception): return fail_log +# Server field in the spec has to be adjusted so that validation does not fail on the server url +def adjust_spec(path_to_file: str, endpoint: str, domain: str): + data = adjust_server(path_to_file=path_to_file, endpoint=endpoint) + data = adjust_server_in_well_known(data=data, endpoint=domain) + return Spec.from_dict(data, validator=None) + + def adjust_server(path_to_file, endpoint): with open(path_to_file, "r") as file: data = yaml.safe_load(file) @@ -226,15 +233,8 @@ def adjust_server(path_to_file, endpoint): return data -def adjust_spec(path_to_file: str, endpoint: str, domain: str): - data = adjust_server(path_to_file=path_to_file, endpoint=endpoint) - data = adjust_server_in_well_known(data=data, endpoint=domain) - return Spec.from_dict(data, validator=None) - - def adjust_server_in_well_known(data, endpoint): data["paths"]["/.well-known/openeo"]["get"]["servers"][0]["url"] = endpoint - return data @@ -260,12 +260,6 @@ def unmarshal_commonmark(value): } -def get_examples_path(): - return os.path.join( - os.getcwd(), "src/openeo_test_suite/tests/general/payload_examples" - ) - - def _guess_root(): project_root = Path(openeo_test_suite.__file__).parents[2] candidates = [ @@ -281,12 +275,23 @@ def _guess_root(): ) +def get_examples_path(): + return ( + _guess_root().parents[2] + / "src" + / "openeo_test_suite" + / "tests" + / "general" + / "payload_examples" + ) + + def get_spec_path(): return _guess_root() / "openapi.yaml" -def load_payloads_from_directory(directory_path: str) -> list[dict]: - for filename in pathlib.Path.glob(directory_path, "*.json"): +def load_payloads_from_directory(directory_path: str) -> Iterator[str]: + for filename in pathlib.Path(directory_path).glob("*.json"): file_path = os.path.join(directory_path, filename) with open(file_path, "r") as file: try: