From 7600c89c031b10c2e5fab991885396bf9ced417e Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Tue, 27 Jan 2026 21:47:06 -0500
Subject: [PATCH 01/10] add support for OGC API Publish-Subscribe Workflow -
Part 1: Core (#2146)
---
.github/workflows/main.yml | 1 +
docs/source/configuration.rst | 18 +
docs/source/index.rst | 1 +
docs/source/pubsub.rst | 68 +++
pygeoapi/api/__init__.py | 31 +-
pygeoapi/api/itemtypes.py | 23 +-
pygeoapi/api/processes.py | 8 +-
pygeoapi/api/pubsub.py | 125 +++++
pygeoapi/openapi.py | 5 +
pygeoapi/plugin.py | 6 +-
pygeoapi/provider/base.py | 4 +-
pygeoapi/pubsub/__init__.py | 30 ++
pygeoapi/pubsub/base.py | 107 ++++
pygeoapi/pubsub/http.py | 105 ++++
pygeoapi/pubsub/mqtt.py | 118 +++++
.../schemas/config/pygeoapi-config-0.x.yml | 27 ++
pygeoapi/templates/landing_page.html | 25 +-
pygeoapi/util.py | 14 +-
requirements-pubsub.txt | 1 +
tests/api/test_pubsub.py | 100 ++++
tests/pygeoapi-test-config-pubsub.yml | 458 ++++++++++++++++++
21 files changed, 1255 insertions(+), 20 deletions(-)
create mode 100644 docs/source/pubsub.rst
create mode 100644 pygeoapi/api/pubsub.py
create mode 100644 pygeoapi/pubsub/__init__.py
create mode 100644 pygeoapi/pubsub/base.py
create mode 100644 pygeoapi/pubsub/http.py
create mode 100644 pygeoapi/pubsub/mqtt.py
create mode 100644 requirements-pubsub.txt
create mode 100644 tests/api/test_pubsub.py
create mode 100644 tests/pygeoapi-test-config-pubsub.yml
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 2cb8f54fd..179453e8b 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -126,6 +126,7 @@ jobs:
pip3 install -r requirements-provider.txt
pip3 install -r requirements-manager.txt
pip3 install -r requirements-django.txt
+ pip3 install -r requirements-pubsub.txt
pip3 install .
pip3 install GDAL==`gdal-config --version`
- name: setup test data ⚙️
diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst
index 35ea9f20f..197a859cd 100644
--- a/docs/source/configuration.rst
+++ b/docs/source/configuration.rst
@@ -14,6 +14,7 @@ file whatever you wish; typical filenames end with ``.yml``.
pygeoapi configuration contains the following core sections:
- ``server``: server-wide settings
+- ``pubsub``: Publish-Subscribe settings (optional)
- ``logging``: logging configuration
- ``metadata``: server-wide metadata (contact, licensing, etc.)
- ``resources``: dataset collections, processes and stac-collections offered by the server
@@ -90,6 +91,23 @@ For more information related to API design rules (the ``api_rules`` property in
url_prefix: 'v{api_major}' # adds a /v1 prefix to all URL paths
version_header: X-API-Version # add a response header of this name with the API version
+``pubsub``
+^^^^^^^^^^
+
+The ``pubsub`` section provides directives for enabling publication of CloudEvent messaages on item-based transactions
+
+
+.. code-block:: yaml
+
+ pubsub:
+ broker:
+ type: mqtt
+ url: mqtt://localhost:1883
+ channel: my/service/topic
+
+.. seealso::
+ :ref:`pubsub` for more information on Publish-Subscribe capabilities
+
``logging``
^^^^^^^^^^^
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 4caa2efcc..4579a27b3 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -39,6 +39,7 @@ reference documentation on all aspects of the project.
openapi
publishing/index
transactions
+ pubsub
admin-api
security
plugins
diff --git a/docs/source/pubsub.rst b/docs/source/pubsub.rst
new file mode 100644
index 000000000..747f5dabf
--- /dev/null
+++ b/docs/source/pubsub.rst
@@ -0,0 +1,68 @@
+.. _pubsub:
+
+Publish-Subscribe integration (Pub/Sub)
+=======================================
+
+pygeoapi supports Publish-Subscribe (Pub/Sub) integration by implementing
+the `OGC API Publish-Subscribe Workflow - Part 1: Core`_ (draft) specification.
+
+Pub/Sub integration can be enabled by defining a broker that pycsw can use to
+publish notifications on given topics using CloudEvents (as per the specification).
+
+When enabled, core functionality of Pub/Sub includes:
+
+- displaying the broker link in the OGC API - Records landing (using the ``rel=hub`` link relation)
+- sending a notification message on the following events:
+
+ - feature or record transactions (create, replace, update, delete)
+ - process executions/job creation
+
+The following message queuing protocols are supported:
+
+MQTT
+----
+
+Example directive:
+
+.. code-block:: yaml
+
+ pubsub:
+ broker:
+ type: mqtt
+ url: mqtt://localhost:1883
+ channel: messages/a/data # optional
+ show_link: false # default true
+
+HTTP
+----
+
+Example directive:
+
+.. code-block:: yaml
+
+ pubsub:
+ broker:
+ type: http
+ url: https://ntfy.sh
+ channel: messages-a-data # optional
+ show_link: true # default
+
+.. note::
+
+ For any Pub/Sub endpoints requiring authentication, encode the ``url`` value as follows:
+
+ * ``mqtt://username:password@localhost:1883``
+ * ``https://username:password@localhost``
+
+ As with any section of the pygeoapi configuration, environment variables may be used as needed, for example
+ to set username/password information in a URL. If ``pubsub.broker.url`` contains authentication, and
+ ``pubsub.broker.show_link`` is ``true``, the authentification inforation will be stripped from the URL
+ before displaying it on the landing page.
+
+.. note::
+
+ If a ``channel`` is defined, it is used as a prefix to the relevant OGC API endpoint used.
+
+ If a ``channel`` is not defined, only the relevant OGC API endpoint is used.
+
+.. _`OGC API Publish-Subscribe Workflow - Part 1: Core`: https://docs.ogc.org/DRAFTS/25-030.html
diff --git a/pygeoapi/api/__init__.py b/pygeoapi/api/__init__.py
index b3247f8a7..18951e0e5 100644
--- a/pygeoapi/api/__init__.py
+++ b/pygeoapi/api/__init__.py
@@ -127,7 +127,7 @@ def all_apis() -> dict:
"""
from . import (coverages, environmental_data_retrieval, itemtypes, maps,
- processes, tiles, stac)
+ processes, pubsub, tiles, stac)
return {
'coverage': coverages,
@@ -135,6 +135,7 @@ def all_apis() -> dict:
'itemtypes': itemtypes,
'map': maps,
'process': processes,
+ 'pubsub': pubsub,
'tile': tiles,
'stac': stac
}
@@ -546,6 +547,7 @@ def __init__(self, config: dict, openapi: dict) -> Self | None:
self.api_headers = get_api_rules(self.config).response_headers
self.base_url = get_base_url(self.config)
self.prefetcher = UrlPrefetcher()
+ self.pubsub_client = None
CHARSET[0] = config['server'].get('encoding', 'utf-8')
if config['server'].get('gzip'):
@@ -573,6 +575,10 @@ def __init__(self, config: dict, openapi: dict) -> Self | None:
self.manager = get_manager(self.config)
LOGGER.info('Process manager plugin loaded')
+ if self.config.get('pubsub') is not None:
+ LOGGER.debug('Loading PubSub client')
+ self.pubsub_client = load_plugin('pubsub', self.config['pubsub'])
+
def get_exception(self, status: int, headers: dict, format_: str | None,
code: str, description: str) -> Tuple[dict, int, str]:
"""
@@ -731,6 +737,19 @@ def landing_page(api: API,
'href': f"{api.base_url}/TileMatrixSets?f=html"
}]
+ if api.pubsub_client is not None and api.pubsub_client.show_link:
+ LOGGER.debug('Adding PubSub broker link')
+ pubsub_link = {
+ 'rel': 'hub',
+ 'type': 'application/json',
+ 'title': 'Pub/Sub broker',
+ 'href': api.pubsub_client.broker_safe_url
+ }
+ if api.pubsub_client.channel is not None:
+ pubsub_link['channel'] = api.pubsub_client.channel
+
+ fcm['links'].append(pubsub_link)
+
headers = request.get_response_headers(**api.api_headers)
if request.format == F_HTML: # render
@@ -747,6 +766,13 @@ def landing_page(api: API,
'tile'):
fcm['tile'] = True
+ if api.pubsub_client is not None and api.pubsub_client.show_link:
+ fcm['pubsub'] = {
+ 'name': api.pubsub_client.name,
+ 'url': api.pubsub_client.broker_safe_url,
+ 'channel': api.pubsub_client.channel
+ }
+
content = render_j2_template(
api.tpl_config, api.config['server']['templates'],
'landing_page.html', fcm, request.locale)
@@ -824,6 +850,9 @@ def conformance(api: API, request: APIRequest) -> Tuple[dict, int, str]:
conformance_list.extend(
apis_dict['itemtypes'].CONFORMANCE_CLASSES_RECORDS)
+ if api.pubsub_client is not None:
+ conformance_list.extend(apis_dict['pubsub'].CONFORMANCE_CLASSES)
+
conformance = {
'conformsTo': sorted(list(set(conformance_list)))
}
diff --git a/pygeoapi/api/itemtypes.py b/pygeoapi/api/itemtypes.py
index ca561b9b2..31e229400 100644
--- a/pygeoapi/api/itemtypes.py
+++ b/pygeoapi/api/itemtypes.py
@@ -49,6 +49,7 @@
from pygeoapi import l10n
from pygeoapi.api import evaluate_limit
+from pygeoapi.api.pubsub import publish_message
from pygeoapi.crs import (DEFAULT_CRS, DEFAULT_STORAGE_CRS,
create_crs_transform_spec, get_supported_crs_list,
modify_pygeofilter, transform_bbox,
@@ -750,6 +751,9 @@ def manage_collection_item(
collections = filter_dict_by_key_value(api.config['resources'],
'type', 'collection')
+ http_status = HTTPStatus.OK
+ payload = None
+
if dataset not in collections.keys():
msg = 'Collection not found'
return api.get_exception(
@@ -795,7 +799,8 @@ def manage_collection_item(
if action == 'create':
LOGGER.debug('Creating item')
try:
- identifier = p.create(request.data)
+ payload = request.data
+ identifier = p.create(payload)
except TypeError as err:
msg = str(err)
return api.get_exception(
@@ -808,12 +813,13 @@ def manage_collection_item(
headers['Location'] = f'{api.get_collections_url()}/{dataset}/items/{identifier}' # noqa
- return headers, HTTPStatus.CREATED, ''
+ http_status = HTTPStatus.CREATED
if action == 'update':
LOGGER.debug('Updating item')
try:
- _ = p.update(identifier, request.data)
+ payload = request.data
+ _ = p.update(identifier, payload)
except TypeError as err:
msg = str(err)
return api.get_exception(
@@ -824,7 +830,7 @@ def manage_collection_item(
err.http_status_code, headers, request.format,
err.ogc_exception_code, err.message)
- return headers, HTTPStatus.NO_CONTENT, ''
+ http_status = HTTPStatus.NO_CONTENT
if action == 'delete':
LOGGER.debug('Deleting item')
@@ -835,7 +841,14 @@ def manage_collection_item(
err.http_status_code, headers, request.format,
err.ogc_exception_code, err.message)
- return headers, HTTPStatus.OK, ''
+ http_status = HTTPStatus.OK
+
+ if api.pubsub_client is not None:
+ LOGGER.debug('Publishing message')
+ publish_message(api.pubsub_client, api.base_url, action, dataset,
+ identifier, payload)
+
+ return headers, http_status, ''
def get_collection_item(api: API, request: APIRequest,
diff --git a/pygeoapi/api/processes.py b/pygeoapi/api/processes.py
index 39a165ea0..1d90044a3 100644
--- a/pygeoapi/api/processes.py
+++ b/pygeoapi/api/processes.py
@@ -9,7 +9,7 @@
# Bernhard Mallinger
# Francesco Martinelli
#
-# Copyright (c) 2024 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
# Copyright (c) 2025 Francesco Bartoli
# Copyright (c) 2022 John A Stevenson and Colin Blackburn
# Copyright (c) 2023 Ricardo Garcia Silva
@@ -50,6 +50,7 @@
from pygeoapi import l10n
from pygeoapi.api import evaluate_limit
+from pygeoapi.api.pubsub import publish_message
from pygeoapi.process.base import (
JobNotFoundError,
JobResultNotFoundError,
@@ -531,6 +532,11 @@ def execute_process(api: API, request: APIRequest,
'status': status.value
}
+ if api.pubsub_client is not None:
+ LOGGER.debug('Publishing message')
+ publish_message(api.pubsub_client, api.base_url, 'process', process_id,
+ job_id, response2)
+
return headers, http_status, response2
diff --git a/pygeoapi/api/pubsub.py b/pygeoapi/api/pubsub.py
new file mode 100644
index 000000000..6f0b75a02
--- /dev/null
+++ b/pygeoapi/api/pubsub.py
@@ -0,0 +1,125 @@
+# =================================================================
+
+# Authors: Tom Kralidis
+#
+# Copyright (c) 2026 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+from datetime import datetime, UTC
+import json
+import logging
+import uuid
+from typing import Union
+
+LOGGER = logging.getLogger(__name__)
+
+CONFORMANCE_CLASSES = [
+ 'https://www.opengis.net/spec/ogcapi-pubsub-1/1.0/conf/message-payload-cloudevents-json', # noqa
+ 'https://www.opengis.net/spec/ogcapi-pubsub-1/1.0/conf/discovery'
+]
+
+
+def publish_message(pubsub_client, url: str, action: str,
+ resource: str = None, item: str = None,
+ data: dict = None) -> bool:
+ """
+ Publish broker message
+
+ :param pubsub_client: `pygeoapi.pubsub.BasePubSubClient` instance
+ :param url: `str` of server base URL
+ :param action: `str` of action trigger name (create, update, delete)
+ :param resource: `str` of resource identifier
+ :param item: `str` of item identifier
+ :param data: `dict` of data payload
+
+ :returns: `bool` of whether message publishing was successful
+ """
+
+ if action in ['create', 'update']:
+ channel = f'collections/{resource}'
+ data_ = data
+ media_type = 'application/geo+json'
+ type_ = f'org.ogc.api.collection.item.{action}'
+ elif action == 'delete':
+ channel = f'collections/{resource}'
+ data_ = item
+ media_type = 'text/plain'
+ type_ = f'org.ogc.api.collection.item.{action}'
+ elif action == 'process':
+ channel = f'processes/{resource}'
+ media_type = 'application/json'
+ data_ = data
+ type_ = 'org.ogc.api.job.result'
+
+ if pubsub_client.channel is not None:
+ channel = f'{pubsub_client.channel}/{channel}'
+
+ message = generate_ogc_cloudevent(type_, media_type, url,
+ channel, data_)
+ LOGGER.debug(f'Message: {message}')
+
+ pubsub_client.connect()
+ pubsub_client.pub(channel, json.dumps(message))
+
+
+def generate_ogc_cloudevent(type_: str, media_type: str, source: str,
+ subject: str, data: Union[dict, str]) -> dict:
+ """
+ Generate CloudEvent
+
+ :param type_: `str` of CloudEvents type
+ :param source: `str` of source
+ :param subject: `str` of subject
+ :param media_type: `str` of media type
+ :param data: `str` or `dict` of data
+
+ :returns: `dict` of OGC CloudEvent payload
+ """
+
+ try:
+ data2 = json.loads(data)
+ except Exception:
+ if isinstance(data, bytes):
+ data2 = data.decode('utf-8')
+ else:
+ data2 = data
+
+ message = {
+ 'specversion': '1.0',
+ 'type': type_,
+ 'source': source,
+ 'subject': subject,
+ 'id': str(uuid.uuid4()),
+ 'time': datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%SZ'),
+ 'datacontenttype': media_type,
+ # 'dataschema': 'TODO',
+ 'data': data2
+ }
+
+ return message
+
+
+def get_oas_30(cfg, locale_):
+ return [], {}
diff --git a/pygeoapi/openapi.py b/pygeoapi/openapi.py
index 759335781..334a01952 100644
--- a/pygeoapi/openapi.py
+++ b/pygeoapi/openapi.py
@@ -538,6 +538,11 @@ def get_oas_30(cfg: dict, fail_on_invalid_collection: bool = True) -> dict:
try:
sub_tags, sub_paths = api_module.get_oas_30(cfg, locale_)
+
+ if not sub_tags and not sub_paths:
+ LOGGER.debug('Empty content from {api_name}; skipping')
+ continue
+
oas['paths'].update(sub_paths['paths'])
oas['tags'].extend(sub_tags)
except Exception as err:
diff --git a/pygeoapi/plugin.py b/pygeoapi/plugin.py
index 54f71be0e..19795be15 100644
--- a/pygeoapi/plugin.py
+++ b/pygeoapi/plugin.py
@@ -2,7 +2,7 @@
#
# Authors: Tom Kralidis
#
-# Copyright (c) 2024 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -85,6 +85,10 @@
'MongoDB': 'pygeoapi.process.manager.mongodb_.MongoDBManager',
'TinyDB': 'pygeoapi.process.manager.tinydb_.TinyDBManager',
'PostgreSQL': 'pygeoapi.process.manager.postgresql.PostgreSQLManager'
+ },
+ 'pubsub': {
+ 'HTTP': 'pygeoapi.pubsub.http.HTTPPubSubClient',
+ 'MQTT': 'pygeoapi.pubsub.mqtt.MQTTPubSubClient'
}
}
diff --git a/pygeoapi/provider/base.py b/pygeoapi/provider/base.py
index 0c58d90cd..b1ccb9c43 100644
--- a/pygeoapi/provider/base.py
+++ b/pygeoapi/provider/base.py
@@ -2,7 +2,7 @@
#
# Authors: Tom Kralidis
#
-# Copyright (c) 2025 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -285,7 +285,7 @@ def _load_and_prepare_item(self, item, identifier=None,
msg = 'record already exists'
LOGGER.error(msg)
- raise ProviderInvalidDataError(msg)
+ raise ProviderInvalidDataError(user_msg=msg)
except ProviderItemNotFoundError:
LOGGER.debug('record does not exist')
diff --git a/pygeoapi/pubsub/__init__.py b/pygeoapi/pubsub/__init__.py
new file mode 100644
index 000000000..87d5c01b8
--- /dev/null
+++ b/pygeoapi/pubsub/__init__.py
@@ -0,0 +1,30 @@
+# =================================================================
+#
+# Authors: Tom Kralidis
+#
+# Copyright (c) 2026 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+"""Pub/Sub module"""
diff --git a/pygeoapi/pubsub/base.py b/pygeoapi/pubsub/base.py
new file mode 100644
index 000000000..88cc94b2f
--- /dev/null
+++ b/pygeoapi/pubsub/base.py
@@ -0,0 +1,107 @@
+# =================================================================
+#
+# Authors: Tom Kralidis
+#
+# Copyright (c) 2026 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+import logging
+import random
+from urllib.parse import urlparse
+
+from pygeoapi.error import GenericError
+from pygeoapi.util import remove_url_auth
+
+LOGGER = logging.getLogger(__name__)
+
+
+class BasePubSubClient:
+ """Base Pub/Sub client"""
+
+ def __init__(self, publisher_def: dict):
+ """
+ Initialize object
+
+ :param publisher_def: publisher definition
+
+ :returns: pycsw.broker.base.BasePubSubClient
+ """
+
+ self.type = 'pubsub'
+
+ try:
+ self.name = publisher_def['name']
+ self.broker = publisher_def['broker']['url']
+ except KeyError:
+ raise RuntimeError('name/type/broker.url are required')
+
+ self.broker_url = urlparse(self.broker)
+ self.broker_safe_url = remove_url_auth(self.broker)
+
+ self.show_link = publisher_def['broker'].get('show_link', True)
+ self.channel = publisher_def['broker'].get('channel')
+ self.client_id = f'pygeoapi-pubsub-{random.randint(0, 1000)}'
+
+ def connect(self) -> None:
+ """
+ Connect to a Pub/Sub broker
+
+ :returns: None
+ """
+
+ raise NotImplementedError()
+
+ def pub(self, channel: str, message: str) -> bool:
+ """
+ Publish a message to a broker/channel
+
+ :param channel: `str` of channel
+ :param message: `str` of message
+
+ :returns: `bool` of publish result
+ """
+
+ raise NotImplementedError()
+
+ def __repr__(self):
+ return f' {self.broker_safe_url}'
+
+
+class PubSubClientConnectionError(GenericError):
+ """Pub/Sub client client connection error"""
+
+ default_msg = 'Pub/Sub client connection error (check logs)'
+
+
+class PubSubClientSubscriptionError(GenericError):
+ """Pub/Sub client client subscription error"""
+
+ default_msg = 'Pub/Sub client subscription error (check logs)'
+
+
+class PubSubClientPublishError(GenericError):
+ """Pub/Sub client client publish error"""
+
+ default_msg = 'Pub/Sub client publish error (check logs)'
diff --git a/pygeoapi/pubsub/http.py b/pygeoapi/pubsub/http.py
new file mode 100644
index 000000000..c1144d847
--- /dev/null
+++ b/pygeoapi/pubsub/http.py
@@ -0,0 +1,105 @@
+# =================================================================
+#
+# Authors: Tom Kralidis
+# Angelos Tzotsos
+#
+# Copyright (c) 2026 Tom Kralidis
+# Copyright (c) 2025 Angelos Tzotsos
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+import logging
+
+import requests
+
+from pygeoapi.pubsub.base import BasePubSubClient
+
+LOGGER = logging.getLogger(__name__)
+
+
+class HTTPPubSubClient(BasePubSubClient):
+ """HTTP client"""
+
+ def __init__(self, broker_url):
+ """
+ Initialize object
+
+ :param publisher_def: provider definition
+
+ :returns: pygeoapi.pubsub.http.HTTPPubSubClient
+ """
+
+ super().__init__(broker_url)
+ self.name = 'HTTP'
+ self.type = 'http'
+ self.auth = None
+
+ msg = f'Initializing to broker {self.broker_safe_url} with id {self.client_id}' # noqa
+ LOGGER.debug(msg)
+
+ if None not in [self.broker_url.username, self.broker_url.password]:
+ LOGGER.debug('Setting credentials')
+ self.auth = (
+ self.broker_url.username,
+ self.broker_url.password
+ )
+
+ def connect(self) -> None:
+ """
+ Connect to an HTTP broker
+
+ :returns: None
+ """
+
+ LOGGER.debug('No connection to HTTP')
+ pass
+
+ def pub(self, channel: str, message: str, qos: int = 1) -> bool:
+ """
+ Publish a message to a broker/channel
+
+ :param channel: `str` of topic
+ :param message: `str` of message
+
+ :returns: `bool` of publish result
+ """
+
+ LOGGER.debug(f'Publishing to broker {self.broker_safe_url}')
+ LOGGER.debug(f'Channel: {channel}')
+ LOGGER.debug(f'Message: {message}')
+ LOGGER.debug('Sanitizing channel for HTTP')
+ channel = channel.replace('/', '-')
+ channel = channel.replace(':', '-')
+ LOGGER.debug(f'Sanitized channel for HTTP: {channel}')
+
+ url = f'{self.broker}/{channel}'
+
+ try:
+ response = requests.post(url, auth=self.auth, json=message)
+ response.raise_for_status()
+ except Exception as err:
+ LOGGER.debug(f'Message publishing failed: {err}')
+
+ def __repr__(self):
+ return f' {self.broker_safe_url}'
diff --git a/pygeoapi/pubsub/mqtt.py b/pygeoapi/pubsub/mqtt.py
new file mode 100644
index 000000000..1c9adaf34
--- /dev/null
+++ b/pygeoapi/pubsub/mqtt.py
@@ -0,0 +1,118 @@
+# =================================================================
+#
+# Authors: Tom Kralidis
+#
+# Copyright (c) 2026 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+import logging
+
+from paho.mqtt import client as mqtt_client
+
+from pygeoapi.pubsub.base import BasePubSubClient
+
+LOGGER = logging.getLogger(__name__)
+
+
+class MQTTPubSubClient(BasePubSubClient):
+ """MQTT client"""
+
+ def __init__(self, broker_url):
+ """
+ Initialize object
+
+ :param publisher_def: provider definition
+
+ :returns: pycsw.pubsub.mqtt.MQTTPubSubClient
+ """
+
+ super().__init__(broker_url)
+ self.type = 'mqtt'
+ self.port = self.broker_url.port
+
+ self.userdata = {}
+
+ msg = f'Connecting to broker {self.broker_safe_url} with id {self.client_id}' # noqa
+ LOGGER.debug(msg)
+ self.conn = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION2,
+ client_id=self.client_id)
+
+ self.conn.enable_logger(logger=LOGGER)
+
+ if None not in [self.broker_url.username, self.broker_url.password]:
+ LOGGER.debug('Setting credentials')
+ self.conn.username_pw_set(
+ self.broker_url.username,
+ self.broker_url.password)
+
+ if self.port is None:
+ if self.broker_url.scheme == 'mqtts':
+ self.port = 8883
+ else:
+ self.port = 1883
+
+ if self.broker_url.scheme == 'mqtts':
+ self.conn.tls_set(tls_version=2)
+
+ def connect(self) -> None:
+ """
+ Connect to an MQTT broker
+
+ :returns: None
+ """
+
+ self.conn.connect(self.broker_url.hostname, self.port)
+ LOGGER.debug('Connected to broker')
+
+ def pub(self, channel: str, message: str, qos: int = 1) -> bool:
+ """
+ Publish a message to a broker/channel
+
+ :param channel: `str` of channel
+ :param message: `str` of message
+
+ :returns: `bool` of publish result
+ """
+
+ LOGGER.debug(f'Publishing to broker {self.broker_safe_url}')
+ LOGGER.debug(f'Channel: {channel}')
+ LOGGER.debug(f'Message: {message}')
+
+ result = self.conn.publish(channel, message, qos)
+ LOGGER.debug(f'Result: {result}')
+
+ # TODO: investigate implication
+ # result.wait_for_publish()
+
+ if result.is_published:
+ LOGGER.debug('Message published')
+ return True
+ else:
+ msg = f'Publishing error code: {result[1]}'
+ LOGGER.warning(msg)
+ return False
+
+ def __repr__(self):
+ return f' {self.broker_safe_url}'
diff --git a/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml b/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml
index 8f0ae873e..72a2e0b69 100644
--- a/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml
+++ b/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml
@@ -167,6 +167,33 @@ properties:
- mimetype
- encoding
- map
+ pubsub:
+ type: object
+ description: Pub/Sub settings for event driven notifications
+ properties:
+ name:
+ type: string
+ description: name of pubsub client
+ broker:
+ type: object
+ description: broker definition
+ properties:
+ url:
+ type: string
+ format: uri
+ description: URL of broker
+ channel:
+ type: string
+ description: channel to subscribe to
+ show_link:
+ type: boolean
+ default: true
+ description: whether to display broker link on API responses
+ required:
+ - url
+ required:
+ - name
+ - broker
logging:
type: object
description: logging definitions
diff --git a/pygeoapi/templates/landing_page.html b/pygeoapi/templates/landing_page.html
index 8995e88a5..06f55fda9 100644
--- a/pygeoapi/templates/landing_page.html
+++ b/pygeoapi/templates/landing_page.html
@@ -81,7 +81,22 @@ {% trans %}Jobs{% endtrans %}
{% trans %}Browse jobs{% endtrans %}
- {% endif %}
+ {% endif %}
+ {% if data['tile'] %}
+
+ {% trans %}Tile Matrix Sets{% endtrans %}
+
+ {% trans %}View the Tile Matrix Sets available on this service{% endtrans %}
+
+ {% endif %}
+ {% if data['pubsub'] %}
+
+ {% endif %}
- {% if data['tile'] %}
-
- {% endif %}
diff --git a/pygeoapi/util.py b/pygeoapi/util.py
index a4b3ad0c5..61f658452 100644
--- a/pygeoapi/util.py
+++ b/pygeoapi/util.py
@@ -2,7 +2,7 @@
#
# Authors: Tom Kralidis
#
-# Copyright (c) 2025 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -792,3 +792,15 @@ def get_dataset_formatters(dataset: dict) -> dict:
dataset_formatters[df2.name] = df2
return dataset_formatters
+
+
+def remove_url_auth(url: str) -> str:
+ """
+ Provide a RFC1738 URL without embedded authentication
+ :param url: RFC1738 URL
+ :returns: RFC1738 URL without authentication
+ """
+
+ u = urlparse(url)
+ auth = f'{u.username}:{u.password}@'
+ return url.replace(auth, '')
diff --git a/requirements-pubsub.txt b/requirements-pubsub.txt
new file mode 100644
index 000000000..8579e8b22
--- /dev/null
+++ b/requirements-pubsub.txt
@@ -0,0 +1 @@
+paho-mqtt
diff --git a/tests/api/test_pubsub.py b/tests/api/test_pubsub.py
new file mode 100644
index 000000000..2c30ec4cd
--- /dev/null
+++ b/tests/api/test_pubsub.py
@@ -0,0 +1,100 @@
+# =================================================================
+#
+# Authors: Tom Kralidis
+#
+# Copyright (c) 2026 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+from copy import deepcopy
+import json
+
+import pytest
+
+from pygeoapi.api import API, landing_page
+from pygeoapi.util import yaml_load
+
+from tests.util import get_test_file_path, mock_api_request
+
+
+@pytest.fixture()
+def config():
+ with open(get_test_file_path('pygeoapi-test-config-pubsub.yml')) as fh:
+ return yaml_load(fh)
+
+
+def test_landing_page(config, openapi):
+ api_ = API(config, openapi)
+
+ broker_link = None
+
+ req = mock_api_request()
+ rsp_headers, code, response = landing_page(api_, req)
+
+ content = json.loads(response)
+
+ for link in content['links']:
+ if link.get('rel') == 'hub':
+ broker_link = link
+
+ assert broker_link is not None
+ assert broker_link['href'] == 'mqtt://localhost:1883'
+ assert broker_link['channel'] == 'my/channel'
+
+ config2 = deepcopy(config)
+ config2['pubsub']['broker']['show_link'] = False
+
+ api_ = API(config2, openapi)
+
+ broker_link = None
+
+ req = mock_api_request()
+ rsp_headers, code, response = landing_page(api_, req)
+
+ content = json.loads(response)
+
+ for link in content['links']:
+ if link.get('rel') == 'hub':
+ broker_link = link
+
+ assert broker_link is None
+
+ config2 = deepcopy(config)
+ config2['pubsub']['broker'].pop('channel', None)
+
+ api_ = API(config2, openapi)
+
+ broker_link = None
+
+ req = mock_api_request()
+ rsp_headers, code, response = landing_page(api_, req)
+
+ content = json.loads(response)
+
+ for link in content['links']:
+ if link.get('rel') == 'hub':
+ broker_link = link
+
+ assert broker_link is not None
+ assert 'channel' not in broker_link
diff --git a/tests/pygeoapi-test-config-pubsub.yml b/tests/pygeoapi-test-config-pubsub.yml
new file mode 100644
index 000000000..51ed71d16
--- /dev/null
+++ b/tests/pygeoapi-test-config-pubsub.yml
@@ -0,0 +1,458 @@
+# =================================================================
+#
+# Authors: Tom Kralidis
+#
+# Copyright (c) 2026 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+server:
+ bind:
+ host: 0.0.0.0
+ port: 5000
+ url: http://localhost:5000/
+ mimetype: application/json; charset=UTF-8
+ encoding: utf-8
+ gzip: false
+ languages:
+ # First language is the default language
+ - en-US
+ - fr-CA
+ cors: true
+ pretty_print: true
+ limits:
+ default_items: 10
+ max_items: 10
+ # templates: /path/to/templates
+ map:
+ url: https://tile.openstreetmap.org/{z}/{x}/{y}.png
+ attribution: '© OpenStreetMap contributors '
+ manager:
+ name: TinyDB
+ connection: /tmp/pygeoapi-test-process-manager.db
+ output_dir: /tmp
+
+pubsub:
+ name: MQTT
+ broker:
+ url: mqtt://everyone:everyone@localhost:1883
+ channel: my/channel
+
+logging:
+ level: DEBUG
+ #logfile: /tmp/pygeoapi.log
+
+metadata:
+ identification:
+ title:
+ en: pygeoapi default instance
+ fr: instance par défaut de pygeoapi
+ description:
+ en: pygeoapi provides an API to geospatial data
+ fr: pygeoapi fournit une API aux données géospatiales
+ keywords:
+ en:
+ - geospatial
+ - data
+ - api
+ fr:
+ - géospatiale
+ - données
+ - api
+ keywords_type: theme
+ terms_of_service: https://creativecommons.org/licenses/by/4.0/
+ url: http://example.org
+ license:
+ name: CC-BY 4.0 license
+ url: https://creativecommons.org/licenses/by/4.0/
+ provider:
+ name: Organization Name
+ url: https://pygeoapi.io
+ contact:
+ name: Lastname, Firstname
+ position: Position Title
+ address: Mailing Address
+ city: City
+ stateorprovince: Administrative Area
+ postalcode: Zip or Postal Code
+ country: Country
+ phone: +xx-xxx-xxx-xxxx
+ fax: +xx-xxx-xxx-xxxx
+ email: you@example.org
+ url: Contact URL
+ hours: Hours of Service
+ instructions: During hours of service. Off on weekends.
+ role: pointOfContact
+
+resources:
+ obs:
+ type: collection
+ title:
+ en: Observations
+ fr: Observations
+ description:
+ en: My cool observations
+ fr: Mes belles observations
+ keywords:
+ - observations
+ - monitoring
+ links:
+ - type: text/csv
+ rel: canonical
+ title: data
+ href: https://github.com/mapserver/mapserver/blob/branch-7-0/msautotest/wxs/data/obs.csv
+ hreflang: en-US
+ - type: text/csv
+ rel: alternate
+ title: data
+ href: https://raw.githubusercontent.com/mapserver/mapserver/branch-7-0/msautotest/wxs/data/obs.csv
+ hreflang: en-US
+ linked-data:
+ context:
+ - schema: https://schema.org/
+ stn_id:
+ "@id": schema:identifier
+ "@type": schema:Text
+ datetime:
+ "@type": schema:DateTime
+ "@id": schema:observationDate
+ value:
+ "@type": schema:Number
+ "@id": schema:QuantitativeValue
+ extents:
+ spatial:
+ bbox: [-180,-90,180,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ temporal:
+ begin: 2000-10-30T18:24:39Z
+ end: 2007-10-30T08:57:29Z
+ trs: http://www.opengis.net/def/uom/ISO-8601/0/Gregorian
+ providers:
+ - type: feature
+ name: CSV
+ data: tests/data/obs.csv
+ crs:
+ - http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ - http://www.opengis.net/def/crs/EPSG/0/4326
+ - http://www.opengis.net/def/crs/EPSG/0/3857
+ - http://www.opengis.net/def/crs/EPSG/0/28992
+ storage_crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ id_field: id
+ geometry:
+ x_field: long
+ y_field: lat
+
+ norway_pop:
+ type: collection
+ title: Norwegian urban areas
+ description: Most populated Norwegian urban areas
+ keywords:
+ - population
+ - Norway
+ links:
+ - type: text/html
+ rel: canonical
+ title: information
+ href: https://www.ssb.no/statbank/table/04859/
+ hreflang: nb-NO
+ extents:
+ spatial:
+ bbox: [-180,-90,180,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ providers:
+ - type: feature
+ name: CSV
+ data: tests/data/norwegian_urban_areas.csv
+ id_field: id
+ geometry:
+ x_field: easting
+ y_field: northing
+ crs:
+ - http://www.opengis.net/def/crs/EPSG/0/4258
+ - http://www.opengis.net/def/crs/EPSG/0/25833
+ storage_crs: http://www.opengis.net/def/crs/EPSG/0/25833
+
+ cmip5:
+ type: collection
+ title: CMIP5 sample
+ description: CMIP5 sample
+ keywords:
+ - cmip5
+ - climate
+ extents:
+ spatial:
+ bbox: [-150,40,-45,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ links:
+ - type: text/html
+ rel: canonical
+ title: information
+ href: https://open.canada.ca/data/en/dataset/eddd6eaf-34d7-4452-a994-3d928115a68b
+ hreflang: en-CA
+ providers:
+ - type: coverage
+ name: xarray
+ data: tests/data/CMIP5_rcp8.5_annual_abs_latlon1x1_PCP_pctl25_P1Y.nc
+ x_field: lon
+ y_field: lat
+ time_field: time
+ format:
+ name: NetCDF
+ mimetype: application/x-netcdf
+
+ naturalearth/lakes:
+ type: collection
+ title:
+ en: Large Lakes
+ fr: Grands Lacs
+ description:
+ en: lakes of the world, public domain
+ fr: lacs du monde, domaine public
+ keywords:
+ - lakes
+ links:
+ - type: text/html
+ rel: canonical
+ title: information
+ href: http://www.naturalearthdata.com/
+ hreflang: en-US
+ extents:
+ spatial:
+ bbox: [-180,-90,180,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ temporal:
+ begin: 2011-11-11T11:11:11Z
+ end: null # or empty (either means open ended)
+ providers:
+ - type: feature
+ name: GeoJSON
+ data: tests/data/ne_110m_lakes.geojson
+ id_field: id
+ crs:
+ - http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ storage_crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ storage_crs_coordinate_epoch: 2017.23
+ - type: tile
+ name: MVT-tippecanoe
+ # data: http://localhost:9000/ne_110m_lakes/{z}/{x}/{y}
+ data: tests/data/tiles/ne_110m_lakes
+ options:
+ bounds: [[-124.953634,-16.536406],[109.929807,66.969298]]
+ zoom:
+ min: 0
+ max: 11
+ schemes:
+ - WorldCRS84Quad
+ format:
+ name: pbf
+ mimetype: application/vnd.mapbox-vector-tile
+
+ gdps-temperature:
+ type: collection
+ title: Global Deterministic Prediction System sample
+ description: Global Deterministic Prediction System sample
+ keywords:
+ - gdps
+ - global
+ extents:
+ spatial:
+ bbox: [-180,-90,180,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ links:
+ - type: text/html
+ rel: canonical
+ title: information
+ href: https://eccc-msc.github.io/open-data/msc-data/nwp_gdps/readme_gdps_en
+ hreflang: en-CA
+ providers:
+ - type: coverage
+ name: rasterio
+ data: tests/data/CMC_glb_TMP_TGL_2_latlon.15x.15_2020081000_P000.grib2
+ format:
+ name: GRIB
+ mimetype: application/x-grib2
+
+ icoads-sst:
+ type: collection
+ title: International Comprehensive Ocean-Atmosphere Data Set (ICOADS)
+ description: International Comprehensive Ocean-Atmosphere Data Set (ICOADS)
+ keywords:
+ - icoads
+ - sst
+ - air temperature
+ extents:
+ spatial:
+ bbox: [-180,-90,180,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ links:
+ - type: text/html
+ rel: canonical
+ title: information
+ href: https://psl.noaa.gov/data/gridded/data.coads.1deg.html
+ hreflang: en-US
+ providers:
+ - type: edr
+ name: xarray-edr
+ data: tests/data/coads_sst.nc
+ format:
+ name: NetCDF
+ mimetype: application/x-netcdf
+
+ usgs-prism:
+ type: collection
+ title: Parameter-elevation Regressions on Independent Slopes Model (PRISM)
+ description: PRISM Monthly Climate Data for the Continental United States
+ keywords:
+ - temperature
+ - precipitation
+ extents:
+ spatial:
+ bbox: [-125.020836, 24.104166, -66.520836, 49.9375]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ links:
+ - type: text/html
+ rel: canonical
+ title: information
+ href: https://cida.usgs.gov/thredds/catalog.html?dataset=cida.usgs.gov/prism_v2
+ hreflang: en-US
+ providers:
+ - type: edr
+ name: xarray-edr
+ data: s3://mdmf/gdp/PRISM_v2.zarr
+ format:
+ name: zarr
+ mimetype: application/zip
+ options:
+ s3:
+ anon: true
+ requester_pays: false
+ client_kwargs:
+ endpoint_url: https://usgs.osn.mghpcc.org/
+
+ objects:
+ type: collection
+ title: GeoJSON objects
+ description: GeoJSON geometry types for GeoSparql and Schema Geometry conversion.
+ keywords:
+ - shapes
+ links:
+ - type: text/html
+ rel: canonical
+ title: data source
+ href: https://en.wikipedia.org/wiki/GeoJSON
+ hreflang: en-US
+ extents:
+ spatial:
+ bbox: [-180,-90,180,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ temporal:
+ begin: null
+ end: null # or empty (either means open ended)
+ providers:
+ - type: feature
+ name: GeoJSON
+ data: tests/data/items.geojson
+ id_field: fid
+ uri_field: uri
+
+ mapserver_world_map:
+ type: collection
+ title: MapServer demo WMS world map
+ description: MapServer demo WMS world map
+ keywords:
+ - MapServer
+ - world map
+ links:
+ - type: text/html
+ rel: canonical
+ title: information
+ href: https://demo.mapserver.org
+ hreflang: en-US
+ extents:
+ spatial:
+ bbox: [-180,-90,180,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ custom-extent:
+ url: https://example.org/custom-extent
+ units: °C
+ range: [0, 10]
+ values: [0, 5, 10]
+ providers:
+ - type: map
+ name: WMSFacade
+ data: https://demo.mapserver.org/cgi-bin/msautotest
+ options:
+ layer: world_latlong
+ style: default
+ format:
+ name: png
+ mimetype: image/png
+
+ canada-metadata:
+ type: collection
+ title:
+ en: Open Canada sample data
+ fr: Exemple de donn\u00e9es Canada Ouvert
+ description:
+ en: Sample metadata records from open.canada.ca
+ fr: Exemples d'enregistrements de m\u00e9tadonn\u00e9es sur ouvert.canada.ca
+ keywords:
+ en:
+ - canada
+ - open data
+ fr:
+ - canada
+ - donn\u00e9es ouvertes
+ links:
+ - type: text/html
+ rel: canonical
+ title: information
+ href: https://open.canada.ca/en/open-data
+ hreflang: en-CA
+ - type: text/html
+ rel: alternate
+ title: informations
+ href: https://ouvert.canada.ca/fr/donnees-ouvertes
+ hreflang: fr-CA
+ extents:
+ spatial:
+ bbox: [-180,-90,180,90]
+ crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ providers:
+ - type: record
+ name: TinyDBCatalogue
+ data: tests/data/open.canada.ca/sample-records.tinydb
+ id_field: externalId
+ time_field: created
+ title_field: title
+
+ hello-world:
+ type: process
+ processor:
+ name: HelloWorld
+
+ pygeometa-metadata-validate:
+ type: process
+ processor:
+ name: pygeometa.pygeoapi_plugin.PygeometaMetadataValidateProcessor
From b0bc695b5d43975031de9dda9b9f819f9f93dcf9 Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Wed, 28 Jan 2026 12:55:23 -0500
Subject: [PATCH 02/10] update docs
---
docs/source/pubsub.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/source/pubsub.rst b/docs/source/pubsub.rst
index 747f5dabf..3e6726169 100644
--- a/docs/source/pubsub.rst
+++ b/docs/source/pubsub.rst
@@ -27,8 +27,8 @@ Example directive:
.. code-block:: yaml
pubsub:
+ name: MQTT
broker:
- type: mqtt
url: mqtt://localhost:1883
channel: messages/a/data # optional
show_link: false # default true
@@ -41,8 +41,8 @@ Example directive:
.. code-block:: yaml
pubsub:
+ name: HTTP
broker:
- type: http
url: https://ntfy.sh
channel: messages-a-data # optional
show_link: true # default
From d021f6c2744cf6c154d54c4ab4bb3b332bad8383 Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Wed, 28 Jan 2026 13:00:48 -0500
Subject: [PATCH 03/10] update docs
---
docs/source/configuration.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst
index 197a859cd..8cab94f52 100644
--- a/docs/source/configuration.rst
+++ b/docs/source/configuration.rst
@@ -100,8 +100,8 @@ The ``pubsub`` section provides directives for enabling publication of CloudEven
.. code-block:: yaml
pubsub:
+ name: MQTT
broker:
- type: mqtt
url: mqtt://localhost:1883
channel: my/service/topic
From 01495541083efa0bef286ece382481bf1b105120 Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Wed, 28 Jan 2026 13:53:15 -0500
Subject: [PATCH 04/10] fix API deletion on not found items in backend
---
pygeoapi/api/itemtypes.py | 10 +++++++++-
tests/provider/test_postgresql_provider.py | 7 +++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/pygeoapi/api/itemtypes.py b/pygeoapi/api/itemtypes.py
index 31e229400..19306f57e 100644
--- a/pygeoapi/api/itemtypes.py
+++ b/pygeoapi/api/itemtypes.py
@@ -59,7 +59,8 @@
from pygeoapi.openapi import get_oas_30_parameters
from pygeoapi.plugin import load_plugin, PLUGINS
from pygeoapi.provider.base import (
- ProviderGenericError, ProviderTypeError, SchemaType)
+ ProviderGenericError, ProviderItemNotFoundError,
+ ProviderTypeError, SchemaType)
from pygeoapi.util import (filter_providers_by_type, to_json,
filter_dict_by_key_value, str2bool,
@@ -834,6 +835,13 @@ def manage_collection_item(
if action == 'delete':
LOGGER.debug('Deleting item')
+ try:
+ _ = p.get(identifier)
+ except ProviderItemNotFoundError as err:
+ return api.get_exception(
+ err.http_status_code, headers, request.format,
+ err.ogc_exception_code, err.message)
+
try:
_ = p.delete(identifier)
except ProviderGenericError as err:
diff --git a/tests/provider/test_postgresql_provider.py b/tests/provider/test_postgresql_provider.py
index c8cb8140e..06d8ab619 100644
--- a/tests/provider/test_postgresql_provider.py
+++ b/tests/provider/test_postgresql_provider.py
@@ -892,6 +892,13 @@ def test_transaction_basic_workflow(pg_api_, data):
identifier=123)
assert code == HTTPStatus.OK
+ # delete again (item should not be in backend)
+ req = mock_api_request(data=data)
+ headers, code, content = manage_collection_item(
+ pg_api_, req, action='delete', dataset='hot_osm_waterways',
+ identifier=123)
+ assert code == HTTPStatus.BAD_REQUEST
+
def test_transaction_create_handles_invalid_input_data(pg_api_, data):
data_parsed = json.loads(data)
From 4ccd1b720b0eb507c1e0d09c7577031544a7e451 Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Wed, 28 Jan 2026 14:18:59 -0500
Subject: [PATCH 05/10] fix ref
---
tests/provider/test_postgresql_provider.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/provider/test_postgresql_provider.py b/tests/provider/test_postgresql_provider.py
index 06d8ab619..da3d0f99e 100644
--- a/tests/provider/test_postgresql_provider.py
+++ b/tests/provider/test_postgresql_provider.py
@@ -897,7 +897,7 @@ def test_transaction_basic_workflow(pg_api_, data):
headers, code, content = manage_collection_item(
pg_api_, req, action='delete', dataset='hot_osm_waterways',
identifier=123)
- assert code == HTTPStatus.BAD_REQUEST
+ assert code == HTTPStatus.NOT_FOUND
def test_transaction_create_handles_invalid_input_data(pg_api_, data):
From d3952ff9c52190e99865bc56a3e0f5c8c0a87291 Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Wed, 28 Jan 2026 18:23:17 -0500
Subject: [PATCH 06/10] fix docs
---
docs/source/pubsub.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/source/pubsub.rst b/docs/source/pubsub.rst
index 3e6726169..4e313e0e9 100644
--- a/docs/source/pubsub.rst
+++ b/docs/source/pubsub.rst
@@ -11,7 +11,7 @@ publish notifications on given topics using CloudEvents (as per the specificatio
When enabled, core functionality of Pub/Sub includes:
-- displaying the broker link in the OGC API - Records landing (using the ``rel=hub`` link relation)
+- displaying the broker link in the OGC API landing page (using the ``rel=hub`` link relation)
- sending a notification message on the following events:
- feature or record transactions (create, replace, update, delete)
From 982edfb0ec330b10d2647f6ce3ee612c2c8927bb Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Thu, 29 Jan 2026 00:48:36 -0500
Subject: [PATCH 07/10] add AsyncAPI support
---
docker/entrypoint.sh | 9 +
docs/source/pubsub.rst | 14 +-
locale/en/LC_MESSAGES/messages.po | 18 +
pygeoapi/__init__.py | 5 +-
pygeoapi/api/__init__.py | 63 +-
pygeoapi/asyncapi.py | 292 +
pygeoapi/django_/urls.py | 3 +-
pygeoapi/django_/views.py | 14 +-
pygeoapi/flask_app.py | 17 +-
pygeoapi/openapi.py | 1 +
pygeoapi/pubsub/base.py | 2 +-
.../schemas/asyncapi/asyncapi-3.0.0.json | 9077 +++++++++++++++++
.../schemas/config/pygeoapi-config-0.x.yml | 6 +-
pygeoapi/starlette_app.py | 18 +-
pygeoapi/templates/asyncapi.html | 24 +
pygeoapi/templates/landing_page.html | 11 +
pygeoapi/util.py | 2 +-
tests/api/test_pubsub.py | 14 +-
tests/conftest.py | 6 +
tests/pygeoapi-test-asyncapi.yml | 56 +
20 files changed, 9627 insertions(+), 25 deletions(-)
create mode 100644 pygeoapi/asyncapi.py
create mode 100644 pygeoapi/resources/schemas/asyncapi/asyncapi-3.0.0.json
create mode 100644 pygeoapi/templates/asyncapi.html
create mode 100644 tests/pygeoapi-test-asyncapi.yml
diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh
index 91be8913e..ae70a87eb 100755
--- a/docker/entrypoint.sh
+++ b/docker/entrypoint.sh
@@ -46,6 +46,9 @@ fi
if [[ -z "$PYGEOAPI_OPENAPI" ]]; then
export PYGEOAPI_OPENAPI="${PYGEOAPI_HOME}/local.openapi.yml"
fi
+if [[ -z "$PYGEOAPI_ASYNCAPI" ]]; then
+ export PYGEOAPI_ASYNCAPI="${PYGEOAPI_HOME}/local.asyncapi.yml"
+fi
# gunicorn env settings with defaults
SCRIPT_NAME=${SCRIPT_NAME:=/}
@@ -87,6 +90,12 @@ echo "Trying to generate openapi.yml"
echo "openapi.yml generated continue to pygeoapi"
+echo "Trying to generate asyncapi.yml"
+/venv/bin/pygeoapi asyncapi generate ${PYGEOAPI_CONFIG} --output-file ${PYGEOAPI_ASYNCAPI}
+
+[[ $? -ne 0 ]] && error "asyncapi.yml could not be generated ERROR"
+echo "asyncapi.yml generated continue to pygeoapi"
+
start_gunicorn() {
# SCRIPT_NAME should not have value '/'
[[ "${SCRIPT_NAME}" = '/' ]] && export SCRIPT_NAME="" && echo "make SCRIPT_NAME empty from /"
diff --git a/docs/source/pubsub.rst b/docs/source/pubsub.rst
index 4e313e0e9..5465b8171 100644
--- a/docs/source/pubsub.rst
+++ b/docs/source/pubsub.rst
@@ -11,7 +11,13 @@ publish notifications on given topics using CloudEvents (as per the specificatio
When enabled, core functionality of Pub/Sub includes:
-- displaying the broker link in the OGC API landing page (using the ``rel=hub`` link relation)
+- providing an AsyncAPI document (JSON and HTML)
+- providing the following links on the OGC API landing page:
+
+ - the broker link (``rel=hub`` link relation)
+ - the AsyncAPI JSON link (``rel=service-desc`` link relation and ``type=application/asyncapi+json`` media type)
+ - the AsyncAPI HTML link (``rel=service-doc`` link relation and ``type=text/html`` media type)
+
- sending a notification message on the following events:
- feature or record transactions (create, replace, update, delete)
@@ -31,7 +37,7 @@ Example directive:
broker:
url: mqtt://localhost:1883
channel: messages/a/data # optional
- show_link: false # default true
+ hidden: false # default
HTTP
----
@@ -45,7 +51,7 @@ Example directive:
broker:
url: https://ntfy.sh
channel: messages-a-data # optional
- show_link: true # default
+ hidden: true # default false
.. note::
@@ -56,7 +62,7 @@ Example directive:
As with any section of the pygeoapi configuration, environment variables may be used as needed, for example
to set username/password information in a URL. If ``pubsub.broker.url`` contains authentication, and
- ``pubsub.broker.show_link`` is ``true``, the authentification inforation will be stripped from the URL
+ ``pubsub.broker.hidden`` is ``false``, the authentication information will be stripped from the URL
before displaying it on the landing page.
.. note::
diff --git a/locale/en/LC_MESSAGES/messages.po b/locale/en/LC_MESSAGES/messages.po
index 17a2698e9..34ad8c485 100644
--- a/locale/en/LC_MESSAGES/messages.po
+++ b/locale/en/LC_MESSAGES/messages.po
@@ -736,3 +736,21 @@ msgstr ""
msgid "Instances"
msgstr ""
+
+msgid "Pub/Sub Notifications"
+msgstr ""
+
+msgid "Pub/Sub broker"
+msgstr ""
+
+msgid "Subscribe to notifications from this service"
+msgstr ""
+
+msgid "AsyncAPI Definition"
+msgstr ""
+
+msgid "The AsyncAPI document as HTML"
+msgstr ""
+
+msgid "The AsyncAPI document as JSON"
+msgstr ""
diff --git a/pygeoapi/__init__.py b/pygeoapi/__init__.py
index f62d8c5a2..30f235f00 100644
--- a/pygeoapi/__init__.py
+++ b/pygeoapi/__init__.py
@@ -3,7 +3,7 @@
# Authors: Tom Kralidis
# Ricardo Garcia Silva
#
-# Copyright (c) 2021 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
# Copyright (c) 2023 Ricardo Garcia Silva
# Copyright (c) 2025 Angelos Tzotsos
#
@@ -38,6 +38,8 @@
from importlib.metadata import entry_points
except ImportError:
from importlib_metadata import entry_points
+
+from pygeoapi.asyncapi import asyncapi
from pygeoapi.config import config
from pygeoapi.openapi import openapi
@@ -110,3 +112,4 @@ def serve(ctx, server):
cli.add_command(config)
cli.add_command(openapi)
+cli.add_command(asyncapi)
diff --git a/pygeoapi/api/__init__.py b/pygeoapi/api/__init__.py
index 18951e0e5..07fcd8f61 100644
--- a/pygeoapi/api/__init__.py
+++ b/pygeoapi/api/__init__.py
@@ -532,18 +532,21 @@ def get_request_headers(self, headers: dict) -> dict:
class API:
"""API object"""
- def __init__(self, config: dict, openapi: dict) -> Self | None:
+ def __init__(self, config: dict, openapi: dict,
+ asyncapi: dict = None) -> Self | None:
"""
constructor
:param config: configuration dict
:param openapi: openapi dict
+ :param asyncapi: asyncapi dict
:returns: `pygeoapi.API` instance
"""
self.config = config
self.openapi = openapi
+ self.asyncapi = asyncapi
self.api_headers = get_api_rules(self.config).response_headers
self.base_url = get_base_url(self.config)
self.prefetcher = UrlPrefetcher()
@@ -737,12 +740,12 @@ def landing_page(api: API,
'href': f"{api.base_url}/TileMatrixSets?f=html"
}]
- if api.pubsub_client is not None and api.pubsub_client.show_link:
+ if api.pubsub_client is not None and not api.pubsub_client.hidden:
LOGGER.debug('Adding PubSub broker link')
pubsub_link = {
'rel': 'hub',
'type': 'application/json',
- 'title': 'Pub/Sub broker',
+ 'title': l10n.translate('Pub/Sub broker', request.locale),
'href': api.pubsub_client.broker_safe_url
}
if api.pubsub_client.channel is not None:
@@ -750,6 +753,20 @@ def landing_page(api: API,
fcm['links'].append(pubsub_link)
+ if api.asyncapi is not None:
+ fcm['links'].append({
+ 'rel': 'service-doc',
+ 'type': 'text/html',
+ 'title': l10n.translate('The AsyncAPI definition as HTML', request.locale), # noqa
+ 'href': f'{api.base_url}/asyncapi?f=html'
+ })
+ fcm['links'].append({
+ 'rel': 'service-desc',
+ 'type': 'application/asyncapi+json',
+ 'title': l10n.translate('The AsyncAPI definition as JSON', request.locale), # noqa
+ 'href': f'{api.base_url}/asyncapi?f=json'
+ })
+
headers = request.get_response_headers(**api.api_headers)
if request.format == F_HTML: # render
@@ -766,11 +783,12 @@ def landing_page(api: API,
'tile'):
fcm['tile'] = True
- if api.pubsub_client is not None and api.pubsub_client.show_link:
+ if api.pubsub_client is not None and not api.pubsub_client.hidden:
fcm['pubsub'] = {
'name': api.pubsub_client.name,
'url': api.pubsub_client.broker_safe_url,
- 'channel': api.pubsub_client.channel
+ 'channel': api.pubsub_client.channel,
+ 'asyncapi': api.asyncapi
}
content = render_j2_template(
@@ -821,6 +839,41 @@ def openapi_(api: API, request: APIRequest) -> Tuple[dict, int, str]:
return headers, HTTPStatus.OK, api.openapi
+def asyncapi_(api: API, request: APIRequest) -> Tuple[dict, int, str]:
+ """
+ Provide AsyncAPI document
+
+ :param request: A request object
+
+ :returns: tuple of headers, status code, content
+ """
+
+ headers = request.get_response_headers(**api.api_headers)
+
+ if not api.asyncapi:
+ msg = 'AsyncAPI not supported/configured'
+ return api.get_exception(
+ HTTPStatus.NOT_IMPLEMENTED, headers, request.format,
+ 'NoApplicableCode', msg)
+
+ if request.format == F_HTML:
+ template = 'asyncapi.html'
+
+ path = f'{api.base_url}/asyncapi'
+ data = {
+ 'asyncapi-document-path': path
+ }
+ content = render_j2_template(
+ api.tpl_config, api.config['server']['templates'], template, data,
+ request.locale)
+
+ return headers, HTTPStatus.OK, content
+
+ headers['Content-Type'] = 'application/asyncapi+json'
+
+ return headers, HTTPStatus.OK, to_json(api.asyncapi, api.pretty_print)
+
+
def conformance(api: API, request: APIRequest) -> Tuple[dict, int, str]:
"""
Provide conformance definition
diff --git a/pygeoapi/asyncapi.py b/pygeoapi/asyncapi.py
new file mode 100644
index 000000000..363ffa610
--- /dev/null
+++ b/pygeoapi/asyncapi.py
@@ -0,0 +1,292 @@
+# =================================================================
+#
+# Authors: Tom Kralidis
+#
+# Copyright (c) 2026 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+import os
+import json
+import logging
+from pathlib import Path
+from urllib.parse import urlparse
+
+import click
+from jsonschema import validate as jsonschema_validate
+import yaml
+
+from pygeoapi import __version__, l10n
+from pygeoapi.models.openapi import OAPIFormat
+from pygeoapi.util import to_json, yaml_load, remove_url_auth
+
+LOGGER = logging.getLogger(__name__)
+
+THISDIR = os.path.dirname(os.path.realpath(__file__))
+
+
+def gen_asyncapi(cfg: dict) -> dict:
+ """
+ Generate an AsyncAPI document
+
+ :param cfg: `dict` of pygeoapi configuration
+
+ :returns: `dict` of AsyncAPI document
+ """
+
+ server_locales = l10n.get_locales(cfg)
+ locale_ = server_locales[0]
+
+ LOGGER.debug('Generating AsyncAPI document')
+
+ title = l10n.translate(cfg['metadata']['identification']['title'], locale_) # noqa
+ description = l10n.translate(cfg['metadata']['identification']['description'], locale_) # noqa
+ tags = l10n.translate(cfg['metadata']['identification']['keywords'], locale_) # noqa
+
+ u = cfg['pubsub']['broker']['url']
+ up = urlparse(u)
+ protocol = up.scheme
+ url = remove_url_auth(u).replace(f'{protocol}://', '')
+
+ a = {
+ 'asyncapi': '3.0.0',
+ 'id': cfg['server']['url'],
+ 'defaultContentType': 'application/json',
+ 'info': {
+ 'version': __version__,
+ 'title': title,
+ 'description': description,
+ 'license': {
+ 'name': cfg['metadata']['license']['name'],
+ 'url': cfg['metadata']['license']['url']
+ },
+ 'contact': {
+ 'name': cfg['metadata']['contact']['name'],
+ 'email': cfg['metadata']['contact']['email']
+ },
+ 'tags': [{'name': tag} for tag in tags],
+ 'externalDocs': {
+ 'url': cfg['metadata']['identification']['url']
+ },
+ },
+ 'servers': {
+ 'default': {
+ 'host': url,
+ 'protocol': protocol,
+ 'description': description
+ }
+ },
+ 'channels': {},
+ 'operations': {}
+ }
+ if cfg['metadata']['contact']['url'].startswith('http'):
+ a['info']['contact']['url'] = cfg['metadata']['contact']['url']
+
+ if cfg['pubsub']['broker'].get('channel') is not None:
+ channel_prefix = cfg['pubsub']['broker']['channel']
+ else:
+ channel_prefix = ''
+
+ LOGGER.debug('Generating channels foreach collection')
+ for key, value in cfg['resources'].items():
+ if value['type'] not in ['collection']:
+ LOGGER.debug('Skipping')
+ continue
+
+ title = l10n.translate(value['title'], locale_)
+ channel_address = f'{channel_prefix}/collections/{key}'
+
+ channel = {
+ 'description': title,
+ 'address': channel_address,
+ 'messages': {
+ 'DefaultMessage': {
+ 'payload': {
+ '$ref': 'https://raw.githubusercontent.com/wmo-im/wis2-monitoring-events/refs/heads/main/schemas/cloudevents-v1.0.2.yaml' # noqa
+ }
+ }
+ }
+ }
+
+ operation = {
+ f'publish-{key}': {
+ 'action': 'send',
+ 'channel': {
+ '$ref': f'#/channels/notify-{key}'
+ }
+ },
+ f'consume-{key}': {
+ 'action': 'receive',
+ 'channel': {
+ '$ref': f'#/channels/notify-{key}'
+ }
+ }
+ }
+
+ a['channels'][f'notify-{key}'] = channel
+ a['operations'].update(operation)
+
+ return a
+
+
+def get_asyncapi(cfg, version='3.0'):
+ """
+ Stub to generate AsyncAPI Document
+
+ :param cfg: configuration object
+ :param version: version of AsyncAPI (default 3.0)
+
+ :returns: AsyncAPI definition YAML dict
+ """
+
+ if version == '3.0':
+ return gen_asyncapi(cfg)
+ else:
+ raise RuntimeError('AsyncAPI version not supported')
+
+
+def validate_asyncapi_document(instance_dict):
+ """
+ Validate an AsyncAPI document against the AsyncAPI schema
+
+ :param instance_dict: dict of AsyncAPI instance
+
+ :returns: `bool` of validation
+ """
+
+ schema_file = os.path.join(
+ THISDIR, 'resources', 'schemas', 'asyncapi', 'asyncapi-3.0.0.json')
+
+ LOGGER.debug(f'Validating against {schema_file}')
+ with open(schema_file) as fh2:
+ schema_dict = json.load(fh2)
+ jsonschema_validate(instance_dict, schema_dict)
+
+ return True
+
+
+def generate_asyncapi_document(cfg: dict, output_format: OAPIFormat):
+ """
+ Generate an AsyncAPI document from the configuration file
+
+ :param cfg: `dict` of configuration
+ :param output_format: output format for AsyncAPI document
+
+ :returns: content of the AsyncAPI document in the output
+ format requested
+ """
+
+ pretty_print = cfg['server'].get('pretty_print', False)
+
+ if output_format == 'yaml':
+ content = yaml.safe_dump(get_asyncapi(cfg), default_flow_style=False)
+ else:
+ content = to_json(get_asyncapi(cfg), pretty=pretty_print)
+ return content
+
+
+def load_asyncapi_document() -> dict:
+ """
+ Open AsyncAPI document from `PYGEOAPI_ASYNCAPI` environment variable
+
+ :returns: `dict` of AsyncAPI document
+ """
+
+ pygeoapi_asyncapi = os.environ.get('PYGEOAPI_ASYNCAPI')
+
+ if pygeoapi_asyncapi is None:
+ LOGGER.debug('PYGEOAPI_ASYNCAPI environment not set')
+ return {}
+
+ if not os.path.exists(pygeoapi_asyncapi):
+ msg = (f'AsyncAPI document {pygeoapi_asyncapi} does not exist. '
+ 'Please generate before starting pygeoapi')
+ LOGGER.error(msg)
+ raise RuntimeError(msg)
+
+ with open(pygeoapi_asyncapi, encoding='utf8') as ff:
+ if pygeoapi_asyncapi.endswith(('.yaml', '.yml')):
+ asyncapi_ = yaml_load(ff)
+ else: # JSON string, do not transform
+ asyncapi_ = ff.read()
+
+ return asyncapi_
+
+
+@click.group()
+def asyncapi():
+ """AsyncAPI management"""
+ pass
+
+
+@click.command()
+@click.pass_context
+@click.argument('config_file', type=click.File(encoding='utf-8'))
+@click.option('--format', '-f', 'format_', type=click.Choice(['json', 'yaml']),
+ default='yaml', help='output format (json|yaml)')
+@click.option('--output-file', '-of', type=click.File('w', encoding='utf-8'),
+ help='Name of output file')
+def generate(ctx, config_file, output_file, format_='yaml'):
+ """Generate AsyncAPI Document"""
+
+ if config_file is None:
+ raise click.ClickException('--config/-c required')
+
+ if isinstance(config_file, Path):
+ with config_file.open(mode='r') as cf:
+ cfg = yaml_load(cf)
+ else:
+ cfg = yaml_load(config_file)
+
+ if 'pubsub' not in cfg:
+ click.echo('pubsub not configured; aborting')
+ ctx.exit(1)
+
+ content = generate_asyncapi_document(cfg, format_)
+
+ if output_file is None:
+ click.echo(content)
+ else:
+ click.echo(f'Generating {output_file.name}')
+ output_file.write(content)
+ click.echo('Done')
+
+
+@click.command()
+@click.pass_context
+@click.argument('asyncapi_file', type=click.File())
+def validate(ctx, asyncapi_file):
+ """Validate AsyncAPI Document"""
+
+ if asyncapi_file is None:
+ raise click.ClickException('--asyncapi/-o required')
+
+ click.echo(f'Validating {asyncapi_file.name}')
+ instance = yaml_load(asyncapi_file)
+ validate_asyncapi_document(instance)
+ click.echo('Valid AsyncAPI document')
+
+
+asyncapi.add_command(generate)
+asyncapi.add_command(validate)
diff --git a/pygeoapi/django_/urls.py b/pygeoapi/django_/urls.py
index 37a19d9ef..108705d08 100644
--- a/pygeoapi/django_/urls.py
+++ b/pygeoapi/django_/urls.py
@@ -8,7 +8,7 @@
# Copyright (c) 2025 Francesco Bartoli
# Copyright (c) 2022 Luca Delucchi
# Copyright (c) 2022 Krishna Lodha
-# Copyright (c) 2025 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -71,6 +71,7 @@ def apply_slash_rule(url: str):
urlpatterns = [
path('', views.landing_page, name='landing-page'),
path(apply_slash_rule('openapi/'), views.openapi, name='openapi'),
+ path(apply_slash_rule('asyncapi/'), views.asyncapi, name='asyncapi'),
path(
apply_slash_rule('conformance/'),
views.conformance,
diff --git a/pygeoapi/django_/views.py b/pygeoapi/django_/views.py
index 620581f11..976d4236d 100644
--- a/pygeoapi/django_/views.py
+++ b/pygeoapi/django_/views.py
@@ -8,7 +8,7 @@
# Copyright (c) 2025 Francesco Bartoli
# Copyright (c) 2022 Luca Delucchi
# Copyright (c) 2022 Krishna Lodha
-# Copyright (c) 2025 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -79,6 +79,18 @@ def openapi(request: HttpRequest) -> HttpResponse:
return execute_from_django(core_api.openapi_, request)
+def asyncapi(request: HttpRequest) -> HttpResponse:
+ """
+ AsyncAPI endpoint
+
+ :request Django HTTP Request
+
+ :returns: Django HTTP Response
+ """
+
+ return execute_from_django(core_api.asyncapi_, request)
+
+
def conformance(request: HttpRequest) -> HttpResponse:
"""
OGC API conformance endpoint
diff --git a/pygeoapi/flask_app.py b/pygeoapi/flask_app.py
index f659655fc..1c5676af0 100644
--- a/pygeoapi/flask_app.py
+++ b/pygeoapi/flask_app.py
@@ -3,7 +3,7 @@
# Authors: Tom Kralidis
# Norman Barker
#
-# Copyright (c) 2025 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -46,6 +46,7 @@
import pygeoapi.api.processes as processes_api
import pygeoapi.api.stac as stac_api
import pygeoapi.api.tiles as tiles_api
+from pygeoapi.asyncapi import load_asyncapi_document
from pygeoapi.openapi import load_openapi_document
from pygeoapi.config import get_config
from pygeoapi.util import get_mimetype, get_api_rules
@@ -53,6 +54,7 @@
CONFIG = get_config()
OPENAPI = load_openapi_document()
+ASYNCAPI = load_asyncapi_document()
API_RULES = get_api_rules(CONFIG)
@@ -91,7 +93,7 @@
APP.config['JSONIFY_PRETTYPRINT_REGULAR'] = CONFIG['server'].get(
'pretty_print', True)
-api_ = API(CONFIG, OPENAPI)
+api_ = API(CONFIG, OPENAPI, ASYNCAPI)
OGC_SCHEMAS_LOCATION = CONFIG['server'].get('ogc_schemas_location')
@@ -181,6 +183,17 @@ def openapi():
return execute_from_flask(core_api.openapi_, request)
+@BLUEPRINT.route('/asyncapi')
+def asyncapi():
+ """
+ AsyncAPI endpoint
+
+ :returns: HTTP response
+ """
+
+ return execute_from_flask(core_api.asyncapi_, request)
+
+
@BLUEPRINT.route('/conformance')
def conformance():
"""
diff --git a/pygeoapi/openapi.py b/pygeoapi/openapi.py
index 334a01952..09cfee333 100644
--- a/pygeoapi/openapi.py
+++ b/pygeoapi/openapi.py
@@ -999,6 +999,7 @@ def validate_openapi_document(instance_dict: dict) -> bool:
schema_file = SCHEMASDIR / 'openapi' / 'openapi-3.0.x.json'
+ LOGGER.debug(f'Validating against {schema_file}')
with schema_file.open() as fh2:
schema_dict = json.load(fh2)
jsonschema_validate(instance_dict, schema_dict)
diff --git a/pygeoapi/pubsub/base.py b/pygeoapi/pubsub/base.py
index 88cc94b2f..6523649a1 100644
--- a/pygeoapi/pubsub/base.py
+++ b/pygeoapi/pubsub/base.py
@@ -60,7 +60,7 @@ def __init__(self, publisher_def: dict):
self.broker_url = urlparse(self.broker)
self.broker_safe_url = remove_url_auth(self.broker)
- self.show_link = publisher_def['broker'].get('show_link', True)
+ self.hidden = publisher_def['broker'].get('hidden', False)
self.channel = publisher_def['broker'].get('channel')
self.client_id = f'pygeoapi-pubsub-{random.randint(0, 1000)}'
diff --git a/pygeoapi/resources/schemas/asyncapi/asyncapi-3.0.0.json b/pygeoapi/resources/schemas/asyncapi/asyncapi-3.0.0.json
new file mode 100644
index 000000000..5f63927db
--- /dev/null
+++ b/pygeoapi/resources/schemas/asyncapi/asyncapi-3.0.0.json
@@ -0,0 +1,9077 @@
+{
+ "$id": "http://asyncapi.com/definitions/3.0.0/asyncapi.json",
+ "$schema": "http://json-schema.org/draft-07/schema",
+ "title": "AsyncAPI 3.0.0 schema.",
+ "type": "object",
+ "required": [
+ "asyncapi",
+ "info"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "asyncapi": {
+ "type": "string",
+ "const": "3.0.0",
+ "description": "The AsyncAPI specification version of this document."
+ },
+ "id": {
+ "type": "string",
+ "description": "A unique id representing the application.",
+ "format": "uri"
+ },
+ "info": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/info.json"
+ },
+ "servers": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/servers.json"
+ },
+ "defaultContentType": {
+ "type": "string",
+ "description": "Default content type to use when encoding/decoding a message's payload."
+ },
+ "channels": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/channels.json"
+ },
+ "operations": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operations.json"
+ },
+ "components": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/components.json"
+ }
+ },
+ "definitions": {
+ "http://asyncapi.com/definitions/3.0.0/specificationExtension.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json",
+ "description": "Any property starting with x- is valid.",
+ "additionalProperties": true,
+ "additionalItems": true
+ },
+ "http://asyncapi.com/definitions/3.0.0/info.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/info.json",
+ "description": "The object provides metadata about the API. The metadata can be used by the clients if needed.",
+ "allOf": [
+ {
+ "type": "object",
+ "required": [
+ "version",
+ "title"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "A unique and precise title of the API."
+ },
+ "version": {
+ "type": "string",
+ "description": "A semantic version number of the API."
+ },
+ "description": {
+ "type": "string",
+ "description": "A longer description of the API. Should be different from the title. CommonMark is allowed."
+ },
+ "termsOfService": {
+ "type": "string",
+ "description": "A URL to the Terms of Service for the API. MUST be in the format of a URL.",
+ "format": "uri"
+ },
+ "contact": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/contact.json"
+ },
+ "license": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/license.json"
+ },
+ "tags": {
+ "type": "array",
+ "description": "A list of tags for application API documentation control. Tags can be used for logical grouping of applications.",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/tag.json"
+ }
+ ]
+ },
+ "uniqueItems": true
+ },
+ "externalDocs": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/infoExtensions.json"
+ }
+ ],
+ "examples": [
+ {
+ "title": "AsyncAPI Sample App",
+ "version": "1.0.1",
+ "description": "This is a sample app.",
+ "termsOfService": "https://asyncapi.org/terms/",
+ "contact": {
+ "name": "API Support",
+ "url": "https://www.asyncapi.org/support",
+ "email": "support@asyncapi.org"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
+ },
+ "externalDocs": {
+ "description": "Find more info here",
+ "url": "https://www.asyncapi.org"
+ },
+ "tags": [
+ {
+ "name": "e-commerce"
+ }
+ ]
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/contact.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/contact.json",
+ "type": "object",
+ "description": "Contact information for the exposed API.",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The identifying name of the contact person/organization."
+ },
+ "url": {
+ "type": "string",
+ "description": "The URL pointing to the contact information.",
+ "format": "uri"
+ },
+ "email": {
+ "type": "string",
+ "description": "The email address of the contact person/organization.",
+ "format": "email"
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "examples": [
+ {
+ "name": "API Support",
+ "url": "https://www.example.com/support",
+ "email": "support@example.com"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/license.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/license.json",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the license type. It's encouraged to use an OSI compatible license."
+ },
+ "url": {
+ "type": "string",
+ "description": "The URL pointing to the license.",
+ "format": "uri"
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "examples": [
+ {
+ "name": "Apache 2.0",
+ "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/Reference.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/Reference.json",
+ "type": "object",
+ "description": "A simple object to allow referencing other components in the specification, internally and externally.",
+ "required": [
+ "$ref"
+ ],
+ "properties": {
+ "$ref": {
+ "description": "The reference string.",
+ "$ref": "http://asyncapi.com/definitions/3.0.0/ReferenceObject.json"
+ }
+ },
+ "examples": [
+ {
+ "$ref": "#/components/schemas/Pet"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/ReferenceObject.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/ReferenceObject.json",
+ "type": "string",
+ "format": "uri-reference"
+ },
+ "http://asyncapi.com/definitions/3.0.0/tag.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/tag.json",
+ "type": "object",
+ "description": "Allows adding metadata to a single tag.",
+ "additionalProperties": false,
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the tag."
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for the tag. CommonMark syntax can be used for rich text representation."
+ },
+ "externalDocs": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "examples": [
+ {
+ "name": "user",
+ "description": "User-related messages"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/externalDocs.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/externalDocs.json",
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Allows referencing an external resource for extended documentation.",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "description": {
+ "type": "string",
+ "description": "A short description of the target documentation. CommonMark syntax can be used for rich text representation."
+ },
+ "url": {
+ "type": "string",
+ "description": "The URL for the target documentation. This MUST be in the form of an absolute URL.",
+ "format": "uri"
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "examples": [
+ {
+ "description": "Find more info here",
+ "url": "https://example.com"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/infoExtensions.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/infoExtensions.json",
+ "type": "object",
+ "description": "The object that lists all the extensions of Info",
+ "properties": {
+ "x-x": {
+ "$ref": "http://asyncapi.com/extensions/x/0.1.0/schema.json"
+ },
+ "x-linkedin": {
+ "$ref": "http://asyncapi.com/extensions/linkedin/0.1.0/schema.json"
+ }
+ }
+ },
+ "http://asyncapi.com/extensions/x/0.1.0/schema.json": {
+ "$id": "http://asyncapi.com/extensions/x/0.1.0/schema.json",
+ "type": "string",
+ "description": "This extension allows you to provide the Twitter username of the account representing the team/company of the API.",
+ "example": [
+ "sambhavgupta75",
+ "AsyncAPISpec"
+ ]
+ },
+ "http://asyncapi.com/extensions/linkedin/0.1.0/schema.json": {
+ "$id": "http://asyncapi.com/extensions/linkedin/0.1.0/schema.json",
+ "type": "string",
+ "pattern": "^http(s)?://(www\\.)?linkedin\\.com.*$",
+ "description": "This extension allows you to provide the Linkedin profile URL of the account representing the team/company of the API.",
+ "example": [
+ "https://www.linkedin.com/company/asyncapi/",
+ "https://www.linkedin.com/in/sambhavgupta0705/"
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/servers.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/servers.json",
+ "description": "An object representing multiple servers.",
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/server.json"
+ }
+ ]
+ },
+ "examples": [
+ {
+ "development": {
+ "host": "localhost:5672",
+ "description": "Development AMQP broker.",
+ "protocol": "amqp",
+ "protocolVersion": "0-9-1",
+ "tags": [
+ {
+ "name": "env:development",
+ "description": "This environment is meant for developers to run their own tests."
+ }
+ ]
+ },
+ "staging": {
+ "host": "rabbitmq-staging.in.mycompany.com:5672",
+ "description": "RabbitMQ broker for the staging environment.",
+ "protocol": "amqp",
+ "protocolVersion": "0-9-1",
+ "tags": [
+ {
+ "name": "env:staging",
+ "description": "This environment is a replica of the production environment."
+ }
+ ]
+ },
+ "production": {
+ "host": "rabbitmq.in.mycompany.com:5672",
+ "description": "RabbitMQ broker for the production environment.",
+ "protocol": "amqp",
+ "protocolVersion": "0-9-1",
+ "tags": [
+ {
+ "name": "env:production",
+ "description": "This environment is the live environment available for final users."
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/server.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/server.json",
+ "type": "object",
+ "description": "An object representing a message broker, a server or any other kind of computer program capable of sending and/or receiving data.",
+ "required": [
+ "host",
+ "protocol"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "host": {
+ "type": "string",
+ "description": "The server host name. It MAY include the port. This field supports Server Variables. Variable substitutions will be made when a variable is named in {braces}."
+ },
+ "pathname": {
+ "type": "string",
+ "description": "The path to a resource in the host. This field supports Server Variables. Variable substitutions will be made when a variable is named in {braces}."
+ },
+ "title": {
+ "type": "string",
+ "description": "A human-friendly title for the server."
+ },
+ "summary": {
+ "type": "string",
+ "description": "A brief summary of the server."
+ },
+ "description": {
+ "type": "string",
+ "description": "A longer description of the server. CommonMark is allowed."
+ },
+ "protocol": {
+ "type": "string",
+ "description": "The protocol this server supports for connection."
+ },
+ "protocolVersion": {
+ "type": "string",
+ "description": "An optional string describing the server. CommonMark syntax MAY be used for rich text representation."
+ },
+ "variables": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/serverVariables.json"
+ },
+ "security": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/securityRequirements.json"
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/tag.json"
+ }
+ ]
+ },
+ "uniqueItems": true
+ },
+ "externalDocs": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ },
+ "bindings": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/serverBindingsObject.json"
+ }
+ ]
+ }
+ },
+ "examples": [
+ {
+ "host": "kafka.in.mycompany.com:9092",
+ "description": "Production Kafka broker.",
+ "protocol": "kafka",
+ "protocolVersion": "3.2"
+ },
+ {
+ "host": "rabbitmq.in.mycompany.com:5672",
+ "pathname": "/production",
+ "protocol": "amqp",
+ "description": "Production RabbitMQ broker (uses the `production` vhost)."
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/serverVariables.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/serverVariables.json",
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/serverVariable.json"
+ }
+ ]
+ }
+ },
+ "http://asyncapi.com/definitions/3.0.0/serverVariable.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/serverVariable.json",
+ "type": "object",
+ "description": "An object representing a Server Variable for server URL template substitution.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "enum": {
+ "type": "array",
+ "description": "An enumeration of string values to be used if the substitution options are from a limited set.",
+ "items": {
+ "type": "string"
+ },
+ "uniqueItems": true
+ },
+ "default": {
+ "type": "string",
+ "description": "The default value to use for substitution, and to send, if an alternate value is not supplied."
+ },
+ "description": {
+ "type": "string",
+ "description": "An optional description for the server variable. CommonMark syntax MAY be used for rich text representation."
+ },
+ "examples": {
+ "type": "array",
+ "description": "An array of examples of the server variable.",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "examples": [
+ {
+ "host": "rabbitmq.in.mycompany.com:5672",
+ "pathname": "/{env}",
+ "protocol": "amqp",
+ "description": "RabbitMQ broker. Use the `env` variable to point to either `production` or `staging`.",
+ "variables": {
+ "env": {
+ "description": "Environment to connect to. It can be either `production` or `staging`.",
+ "enum": [
+ "production",
+ "staging"
+ ]
+ }
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/securityRequirements.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/securityRequirements.json",
+ "description": "An array representing security requirements.",
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/SecurityScheme.json"
+ }
+ ]
+ }
+ },
+ "http://asyncapi.com/definitions/3.0.0/SecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/SecurityScheme.json",
+ "description": "Defines a security scheme that can be used by the operations.",
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/userPassword.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/apiKey.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/X509.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/symmetricEncryption.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/asymmetricEncryption.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/HTTPSecurityScheme.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/oauth2Flows.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/openIdConnect.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/SaslSecurityScheme.json"
+ }
+ ],
+ "examples": [
+ {
+ "type": "userPassword"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/userPassword.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/userPassword.json",
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "userPassword"
+ ]
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "type": "userPassword"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/apiKey.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/apiKey.json",
+ "type": "object",
+ "required": [
+ "type",
+ "in"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme",
+ "enum": [
+ "apiKey"
+ ]
+ },
+ "in": {
+ "type": "string",
+ "description": " The location of the API key.",
+ "enum": [
+ "user",
+ "password"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme. CommonMark syntax MAY be used for rich text representation."
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "type": "apiKey",
+ "in": "user"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/X509.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/X509.json",
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "X509"
+ ]
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "type": "X509"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/symmetricEncryption.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/symmetricEncryption.json",
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "symmetricEncryption"
+ ]
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "type": "symmetricEncryption"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/asymmetricEncryption.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/asymmetricEncryption.json",
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme.",
+ "enum": [
+ "asymmetricEncryption"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme."
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false
+ },
+ "http://asyncapi.com/definitions/3.0.0/HTTPSecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/HTTPSecurityScheme.json",
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/NonBearerHTTPSecurityScheme.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/BearerHTTPSecurityScheme.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/APIKeyHTTPSecurityScheme.json"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/NonBearerHTTPSecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/NonBearerHTTPSecurityScheme.json",
+ "not": {
+ "type": "object",
+ "properties": {
+ "scheme": {
+ "type": "string",
+ "description": "A short description for security scheme.",
+ "enum": [
+ "bearer"
+ ]
+ }
+ }
+ },
+ "type": "object",
+ "required": [
+ "scheme",
+ "type"
+ ],
+ "properties": {
+ "scheme": {
+ "type": "string",
+ "description": "The name of the HTTP Authorization scheme to be used in the Authorization header as defined in RFC7235."
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme."
+ },
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme.",
+ "enum": [
+ "http"
+ ]
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false
+ },
+ "http://asyncapi.com/definitions/3.0.0/BearerHTTPSecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/BearerHTTPSecurityScheme.json",
+ "type": "object",
+ "required": [
+ "type",
+ "scheme"
+ ],
+ "properties": {
+ "scheme": {
+ "type": "string",
+ "description": "The name of the HTTP Authorization scheme to be used in the Authorization header as defined in RFC7235.",
+ "enum": [
+ "bearer"
+ ]
+ },
+ "bearerFormat": {
+ "type": "string",
+ "description": "A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes."
+ },
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme.",
+ "enum": [
+ "http"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme. CommonMark syntax MAY be used for rich text representation."
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false
+ },
+ "http://asyncapi.com/definitions/3.0.0/APIKeyHTTPSecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/APIKeyHTTPSecurityScheme.json",
+ "type": "object",
+ "required": [
+ "type",
+ "name",
+ "in"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme.",
+ "enum": [
+ "httpApiKey"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the header, query or cookie parameter to be used."
+ },
+ "in": {
+ "type": "string",
+ "description": "The location of the API key",
+ "enum": [
+ "header",
+ "query",
+ "cookie"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme. CommonMark syntax MAY be used for rich text representation."
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "type": "httpApiKey",
+ "name": "api_key",
+ "in": "header"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/oauth2Flows.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/oauth2Flows.json",
+ "type": "object",
+ "description": "Allows configuration of the supported OAuth Flows.",
+ "required": [
+ "type",
+ "flows"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme.",
+ "enum": [
+ "oauth2"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme."
+ },
+ "flows": {
+ "type": "object",
+ "properties": {
+ "implicit": {
+ "description": "Configuration for the OAuth Implicit flow.",
+ "allOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/oauth2Flow.json"
+ },
+ {
+ "required": [
+ "authorizationUrl",
+ "availableScopes"
+ ]
+ },
+ {
+ "not": {
+ "required": [
+ "tokenUrl"
+ ]
+ }
+ }
+ ]
+ },
+ "password": {
+ "description": "Configuration for the OAuth Resource Owner Protected Credentials flow.",
+ "allOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/oauth2Flow.json"
+ },
+ {
+ "required": [
+ "tokenUrl",
+ "availableScopes"
+ ]
+ },
+ {
+ "not": {
+ "required": [
+ "authorizationUrl"
+ ]
+ }
+ }
+ ]
+ },
+ "clientCredentials": {
+ "description": "Configuration for the OAuth Client Credentials flow.",
+ "allOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/oauth2Flow.json"
+ },
+ {
+ "required": [
+ "tokenUrl",
+ "availableScopes"
+ ]
+ },
+ {
+ "not": {
+ "required": [
+ "authorizationUrl"
+ ]
+ }
+ }
+ ]
+ },
+ "authorizationCode": {
+ "description": "Configuration for the OAuth Authorization Code flow.",
+ "allOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/oauth2Flow.json"
+ },
+ {
+ "required": [
+ "authorizationUrl",
+ "tokenUrl",
+ "availableScopes"
+ ]
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
+ },
+ "scopes": {
+ "type": "array",
+ "description": "List of the needed scope names.",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ }
+ },
+ "http://asyncapi.com/definitions/3.0.0/oauth2Flow.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/oauth2Flow.json",
+ "type": "object",
+ "description": "Configuration details for a supported OAuth Flow",
+ "properties": {
+ "authorizationUrl": {
+ "type": "string",
+ "format": "uri",
+ "description": "The authorization URL to be used for this flow. This MUST be in the form of an absolute URL."
+ },
+ "tokenUrl": {
+ "type": "string",
+ "format": "uri",
+ "description": "The token URL to be used for this flow. This MUST be in the form of an absolute URL."
+ },
+ "refreshUrl": {
+ "type": "string",
+ "format": "uri",
+ "description": "The URL to be used for obtaining refresh tokens. This MUST be in the form of an absolute URL."
+ },
+ "availableScopes": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/oauth2Scopes.json",
+ "description": "The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it."
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "authorizationUrl": "https://example.com/api/oauth/dialog",
+ "tokenUrl": "https://example.com/api/oauth/token",
+ "availableScopes": {
+ "write:pets": "modify pets in your account",
+ "read:pets": "read your pets"
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/oauth2Scopes.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/oauth2Scopes.json",
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "http://asyncapi.com/definitions/3.0.0/openIdConnect.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/openIdConnect.json",
+ "type": "object",
+ "required": [
+ "type",
+ "openIdConnectUrl"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme.",
+ "enum": [
+ "openIdConnect"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme. CommonMark syntax MAY be used for rich text representation."
+ },
+ "openIdConnectUrl": {
+ "type": "string",
+ "format": "uri",
+ "description": "OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of an absolute URL."
+ },
+ "scopes": {
+ "type": "array",
+ "description": "List of the needed scope names. An empty array means no scopes are needed.",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false
+ },
+ "http://asyncapi.com/definitions/3.0.0/SaslSecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/SaslSecurityScheme.json",
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/SaslPlainSecurityScheme.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/SaslScramSecurityScheme.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/SaslGssapiSecurityScheme.json"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/SaslPlainSecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/SaslPlainSecurityScheme.json",
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme. Valid values",
+ "enum": [
+ "plain"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme."
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "type": "scramSha512"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/SaslScramSecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/SaslScramSecurityScheme.json",
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme.",
+ "enum": [
+ "scramSha256",
+ "scramSha512"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme."
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "type": "scramSha512"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/SaslGssapiSecurityScheme.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/SaslGssapiSecurityScheme.json",
+ "type": "object",
+ "required": [
+ "type"
+ ],
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "The type of the security scheme.",
+ "enum": [
+ "gssapi"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description for security scheme."
+ }
+ },
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": false,
+ "examples": [
+ {
+ "type": "scramSha512"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/serverBindingsObject.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/serverBindingsObject.json",
+ "type": "object",
+ "description": "Map describing protocol-specific definitions for a server.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "http": {},
+ "ws": {},
+ "amqp": {},
+ "amqp1": {},
+ "mqtt": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/mqtt/0.2.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/mqtt/0.2.0/server.json"
+ }
+ }
+ ]
+ },
+ "kafka": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.5.0",
+ "0.4.0",
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.5.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.5.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.5.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.4.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.4.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.3.0/server.json"
+ }
+ }
+ ]
+ },
+ "anypointmq": {},
+ "nats": {},
+ "jms": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.0.1"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/jms/0.0.1/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.0.1"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/jms/0.0.1/server.json"
+ }
+ }
+ ]
+ },
+ "sns": {},
+ "sqs": {},
+ "stomp": {},
+ "redis": {},
+ "ibmmq": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/ibmmq/0.1.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/ibmmq/0.1.0/server.json"
+ }
+ }
+ ]
+ },
+ "solace": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.4.0",
+ "0.3.0",
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/solace/0.4.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.4.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/solace/0.4.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/solace/0.3.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/solace/0.2.0/server.json"
+ }
+ }
+ ]
+ },
+ "googlepubsub": {},
+ "pulsar": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/pulsar/0.1.0/server.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/pulsar/0.1.0/server.json"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "http://asyncapi.com/bindings/mqtt/0.2.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/mqtt/0.2.0/server.json",
+ "title": "Server Schema",
+ "description": "This object contains information about the server representation in MQTT.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "clientId": {
+ "type": "string",
+ "description": "The client identifier."
+ },
+ "cleanSession": {
+ "type": "boolean",
+ "description": "Whether to create a persistent connection or not. When 'false', the connection will be persistent. This is called clean start in MQTTv5."
+ },
+ "lastWill": {
+ "type": "object",
+ "description": "Last Will and Testament configuration.",
+ "properties": {
+ "topic": {
+ "type": "string",
+ "description": "The topic where the Last Will and Testament message will be sent."
+ },
+ "qos": {
+ "type": "integer",
+ "enum": [
+ 0,
+ 1,
+ 2
+ ],
+ "description": "Defines how hard the broker/client will try to ensure that the Last Will and Testament message is received. Its value MUST be either 0, 1 or 2."
+ },
+ "message": {
+ "type": "string",
+ "description": "Last Will message."
+ },
+ "retain": {
+ "type": "boolean",
+ "description": "Whether the broker should retain the Last Will and Testament message or not."
+ }
+ }
+ },
+ "keepAlive": {
+ "type": "integer",
+ "description": "Interval in seconds of the longest period of time the broker and the client can endure without sending a message."
+ },
+ "sessionExpiryInterval": {
+ "oneOf": [
+ {
+ "type": "integer",
+ "minimum": 0
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ ],
+ "description": "Interval time in seconds or a Schema Object containing the definition of the interval. The broker maintains a session for a disconnected client until this interval expires."
+ },
+ "maximumPacketSize": {
+ "oneOf": [
+ {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 4294967295
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ ],
+ "description": "Number of bytes or a Schema Object representing the Maximum Packet Size the Client is willing to accept."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "clientId": "guest",
+ "cleanSession": true,
+ "lastWill": {
+ "topic": "/last-wills",
+ "qos": 2,
+ "message": "Guest gone offline.",
+ "retain": false
+ },
+ "keepAlive": 60,
+ "sessionExpiryInterval": 120,
+ "maximumPacketSize": 1024,
+ "bindingVersion": "0.2.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/schema.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "The Schema Object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. This object is a superset of the JSON Schema Specification Draft 07. The empty schema (which allows any instance to validate) MAY be represented by the boolean value true and a schema which allows no instance to validate MAY be represented by the boolean value false.",
+ "allOf": [
+ {
+ "$ref": "http://json-schema.org/draft-07/schema#"
+ },
+ {
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "type": "boolean"
+ }
+ ],
+ "default": {}
+ },
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ }
+ }
+ ],
+ "default": {}
+ },
+ "allOf": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ }
+ },
+ "oneOf": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ }
+ },
+ "anyOf": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ }
+ },
+ "not": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ "properties": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ "default": {}
+ },
+ "patternProperties": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ "default": {}
+ },
+ "propertyNames": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ "contains": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ "discriminator": {
+ "type": "string",
+ "description": "Adds support for polymorphism. The discriminator is the schema property name that is used to differentiate between other schema that inherit this schema. The property name used MUST be defined at this schema and it MUST be in the required property list. When used, the value MUST be the name of this schema or any schema that inherits it. See Composition and Inheritance for more details."
+ },
+ "externalDocs": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ },
+ "deprecated": {
+ "type": "boolean",
+ "description": "Specifies that a schema is deprecated and SHOULD be transitioned out of usage. Default value is false.",
+ "default": false
+ }
+ }
+ }
+ ]
+ },
+ "http://json-schema.org/draft-07/schema": {
+ "$id": "http://json-schema.org/draft-07/schema",
+ "title": "Core schema meta-schema",
+ "definitions": {
+ "schemaArray": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#"
+ }
+ },
+ "nonNegativeInteger": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "nonNegativeIntegerDefault0": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/nonNegativeInteger"
+ },
+ {
+ "default": 0
+ }
+ ]
+ },
+ "simpleTypes": {
+ "enum": [
+ "array",
+ "boolean",
+ "integer",
+ "null",
+ "number",
+ "object",
+ "string"
+ ]
+ },
+ "stringArray": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "uniqueItems": true,
+ "default": []
+ }
+ },
+ "type": [
+ "object",
+ "boolean"
+ ],
+ "properties": {
+ "$id": {
+ "type": "string",
+ "format": "uri-reference"
+ },
+ "$schema": {
+ "type": "string",
+ "format": "uri"
+ },
+ "$ref": {
+ "type": "string",
+ "format": "uri-reference"
+ },
+ "$comment": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": true,
+ "readOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "writeOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "examples": {
+ "type": "array",
+ "items": true
+ },
+ "multipleOf": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "maximum": {
+ "type": "number"
+ },
+ "exclusiveMaximum": {
+ "type": "number"
+ },
+ "minimum": {
+ "type": "number"
+ },
+ "exclusiveMinimum": {
+ "type": "number"
+ },
+ "maxLength": {
+ "$ref": "#/definitions/nonNegativeInteger"
+ },
+ "minLength": {
+ "$ref": "#/definitions/nonNegativeIntegerDefault0"
+ },
+ "pattern": {
+ "type": "string",
+ "format": "regex"
+ },
+ "additionalItems": {
+ "$ref": "#"
+ },
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/schemaArray"
+ }
+ ],
+ "default": true
+ },
+ "maxItems": {
+ "$ref": "#/definitions/nonNegativeInteger"
+ },
+ "minItems": {
+ "$ref": "#/definitions/nonNegativeIntegerDefault0"
+ },
+ "uniqueItems": {
+ "type": "boolean",
+ "default": false
+ },
+ "contains": {
+ "$ref": "#"
+ },
+ "maxProperties": {
+ "$ref": "#/definitions/nonNegativeInteger"
+ },
+ "minProperties": {
+ "$ref": "#/definitions/nonNegativeIntegerDefault0"
+ },
+ "required": {
+ "$ref": "#/definitions/stringArray"
+ },
+ "additionalProperties": {
+ "$ref": "#"
+ },
+ "definitions": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#"
+ },
+ "default": {}
+ },
+ "properties": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#"
+ },
+ "default": {}
+ },
+ "patternProperties": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#"
+ },
+ "propertyNames": {
+ "format": "regex"
+ },
+ "default": {}
+ },
+ "dependencies": {
+ "type": "object",
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/stringArray"
+ }
+ ]
+ }
+ },
+ "propertyNames": {
+ "$ref": "#"
+ },
+ "const": true,
+ "enum": {
+ "type": "array",
+ "items": true,
+ "minItems": 1,
+ "uniqueItems": true
+ },
+ "type": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/simpleTypes"
+ },
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/simpleTypes"
+ },
+ "minItems": 1,
+ "uniqueItems": true
+ }
+ ]
+ },
+ "format": {
+ "type": "string"
+ },
+ "contentMediaType": {
+ "type": "string"
+ },
+ "contentEncoding": {
+ "type": "string"
+ },
+ "if": {
+ "$ref": "#"
+ },
+ "then": {
+ "$ref": "#"
+ },
+ "else": {
+ "$ref": "#"
+ },
+ "allOf": {
+ "$ref": "#/definitions/schemaArray"
+ },
+ "anyOf": {
+ "$ref": "#/definitions/schemaArray"
+ },
+ "oneOf": {
+ "$ref": "#/definitions/schemaArray"
+ },
+ "not": {
+ "$ref": "#"
+ }
+ },
+ "default": true
+ },
+ "http://asyncapi.com/bindings/kafka/0.5.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.5.0/server.json",
+ "title": "Server Schema",
+ "description": "This object contains server connection information to a Kafka broker. This object contains additional information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "schemaRegistryUrl": {
+ "type": "string",
+ "description": "API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used)."
+ },
+ "schemaRegistryVendor": {
+ "type": "string",
+ "description": "The vendor of the Schema Registry and Kafka serdes library that should be used."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.5.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "examples": [
+ {
+ "schemaRegistryUrl": "https://my-schema-registry.com",
+ "schemaRegistryVendor": "confluent",
+ "bindingVersion": "0.5.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.4.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.4.0/server.json",
+ "title": "Server Schema",
+ "description": "This object contains server connection information to a Kafka broker. This object contains additional information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "schemaRegistryUrl": {
+ "type": "string",
+ "description": "API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used)."
+ },
+ "schemaRegistryVendor": {
+ "type": "string",
+ "description": "The vendor of the Schema Registry and Kafka serdes library that should be used."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.4.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "examples": [
+ {
+ "schemaRegistryUrl": "https://my-schema-registry.com",
+ "schemaRegistryVendor": "confluent",
+ "bindingVersion": "0.4.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.3.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.3.0/server.json",
+ "title": "Server Schema",
+ "description": "This object contains server connection information to a Kafka broker. This object contains additional information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "schemaRegistryUrl": {
+ "type": "string",
+ "description": "API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used)."
+ },
+ "schemaRegistryVendor": {
+ "type": "string",
+ "description": "The vendor of the Schema Registry and Kafka serdes library that should be used."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "examples": [
+ {
+ "schemaRegistryUrl": "https://my-schema-registry.com",
+ "schemaRegistryVendor": "confluent",
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/jms/0.0.1/server.json": {
+ "$id": "http://asyncapi.com/bindings/jms/0.0.1/server.json",
+ "title": "Server Schema",
+ "description": "This object contains configuration for describing a JMS broker as an AsyncAPI server. This objects only contains configuration that can not be provided in the AsyncAPI standard server object.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "required": [
+ "jmsConnectionFactory"
+ ],
+ "properties": {
+ "jmsConnectionFactory": {
+ "type": "string",
+ "description": "The classname of the ConnectionFactory implementation for the JMS Provider."
+ },
+ "properties": {
+ "type": "array",
+ "items": {
+ "$ref": "http://asyncapi.com/bindings/jms/0.0.1/server.json#/definitions/property"
+ },
+ "description": "Additional properties to set on the JMS ConnectionFactory implementation for the JMS Provider."
+ },
+ "clientID": {
+ "type": "string",
+ "description": "A client identifier for applications that use this JMS connection factory. If the Client ID Policy is set to 'Restricted' (the default), then configuring a Client ID on the ConnectionFactory prevents more than one JMS client from using a connection from this factory."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.0.1"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "definitions": {
+ "property": {
+ "type": "object",
+ "required": [
+ "name",
+ "value"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of a property"
+ },
+ "value": {
+ "type": [
+ "string",
+ "boolean",
+ "number",
+ "null"
+ ],
+ "description": "The name of a property"
+ }
+ }
+ }
+ },
+ "examples": [
+ {
+ "jmsConnectionFactory": "org.apache.activemq.ActiveMQConnectionFactory",
+ "properties": [
+ {
+ "name": "disableTimeStampsByDefault",
+ "value": false
+ }
+ ],
+ "clientID": "my-application-1",
+ "bindingVersion": "0.0.1"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/ibmmq/0.1.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/ibmmq/0.1.0/server.json",
+ "title": "IBM MQ server bindings object",
+ "description": "This object contains server connection information about the IBM MQ server, referred to as an IBM MQ queue manager. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "groupId": {
+ "type": "string",
+ "description": "Defines a logical group of IBM MQ server objects. This is necessary to specify multi-endpoint configurations used in high availability deployments. If omitted, the server object is not part of a group."
+ },
+ "ccdtQueueManagerName": {
+ "type": "string",
+ "default": "*",
+ "description": "The name of the IBM MQ queue manager to bind to in the CCDT file."
+ },
+ "cipherSpec": {
+ "type": "string",
+ "description": "The recommended cipher specification used to establish a TLS connection between the client and the IBM MQ queue manager. More information on SSL/TLS cipher specifications supported by IBM MQ can be found on this page in the IBM MQ Knowledge Center."
+ },
+ "multiEndpointServer": {
+ "type": "boolean",
+ "default": false,
+ "description": "If 'multiEndpointServer' is 'true' then multiple connections can be workload balanced and applications should not make assumptions as to where messages are processed. Where message ordering, or affinity to specific message resources is necessary, a single endpoint ('multiEndpointServer' = 'false') may be required."
+ },
+ "heartBeatInterval": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 999999,
+ "default": 300,
+ "description": "The recommended value (in seconds) for the heartbeat sent to the queue manager during periods of inactivity. A value of zero means that no heart beats are sent. A value of 1 means that the client will use the value defined by the queue manager. More information on heart beat interval can be found on this page in the IBM MQ Knowledge Center."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "examples": [
+ {
+ "groupId": "PRODCLSTR1",
+ "cipherSpec": "ANY_TLS12_OR_HIGHER",
+ "bindingVersion": "0.1.0"
+ },
+ {
+ "groupId": "PRODCLSTR1",
+ "bindingVersion": "0.1.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/solace/0.4.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/solace/0.4.0/server.json",
+ "title": "Solace server bindings object",
+ "description": "This object contains server connection information about the Solace broker. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "msgVpn": {
+ "type": "string",
+ "description": "The name of the Virtual Private Network to connect to on the Solace broker."
+ },
+ "clientName": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 160,
+ "description": "A unique client name to use to register to the appliance. If specified, it must be a valid Topic name, and a maximum of 160 bytes in length when encoded as UTF-8."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.4.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "examples": [
+ {
+ "msgVpn": "ProdVPN",
+ "bindingVersion": "0.4.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/solace/0.3.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/solace/0.3.0/server.json",
+ "title": "Solace server bindings object",
+ "description": "This object contains server connection information about the Solace broker. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "msgVpn": {
+ "type": "string",
+ "description": "The name of the Virtual Private Network to connect to on the Solace broker."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "examples": [
+ {
+ "msgVpn": "ProdVPN",
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/solace/0.2.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/solace/0.2.0/server.json",
+ "title": "Solace server bindings object",
+ "description": "This object contains server connection information about the Solace broker. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "msvVpn": {
+ "type": "string",
+ "description": "The name of the Virtual Private Network to connect to on the Solace broker."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "examples": [
+ {
+ "msgVpn": "ProdVPN",
+ "bindingVersion": "0.2.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/pulsar/0.1.0/server.json": {
+ "$id": "http://asyncapi.com/bindings/pulsar/0.1.0/server.json",
+ "title": "Server Schema",
+ "description": "This object contains server information of Pulsar broker, which covers cluster and tenant admin configuration. This object contains additional information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "tenant": {
+ "type": "string",
+ "description": "The pulsar tenant. If omitted, 'public' MUST be assumed."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "tenant": "contoso",
+ "bindingVersion": "0.1.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/channels.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/channels.json",
+ "type": "object",
+ "description": "An object containing all the Channel Object definitions the Application MUST use during runtime.",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/channel.json"
+ }
+ ]
+ },
+ "examples": [
+ {
+ "userSignedUp": {
+ "address": "user.signedup",
+ "messages": {
+ "userSignedUp": {
+ "$ref": "#/components/messages/userSignedUp"
+ }
+ }
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/channel.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/channel.json",
+ "type": "object",
+ "description": "Describes a shared communication channel.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "address": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An optional string representation of this channel's address. The address is typically the \"topic name\", \"routing key\", \"event type\", or \"path\". When `null` or absent, it MUST be interpreted as unknown. This is useful when the address is generated dynamically at runtime or can't be known upfront. It MAY contain Channel Address Expressions."
+ },
+ "messages": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/channelMessages.json"
+ },
+ "parameters": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/parameters.json"
+ },
+ "title": {
+ "type": "string",
+ "description": "A human-friendly title for the channel."
+ },
+ "summary": {
+ "type": "string",
+ "description": "A brief summary of the channel."
+ },
+ "description": {
+ "type": "string",
+ "description": "A longer description of the channel. CommonMark is allowed."
+ },
+ "servers": {
+ "type": "array",
+ "description": "The references of the servers on which this channel is available. If absent or empty then this channel must be available on all servers.",
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ "uniqueItems": true
+ },
+ "tags": {
+ "type": "array",
+ "description": "A list of tags for logical grouping of channels.",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/tag.json"
+ }
+ ]
+ },
+ "uniqueItems": true
+ },
+ "externalDocs": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ },
+ "bindings": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/channelBindingsObject.json"
+ }
+ ]
+ }
+ },
+ "examples": [
+ {
+ "address": "users.{userId}",
+ "title": "Users channel",
+ "description": "This channel is used to exchange messages about user events.",
+ "messages": {
+ "userSignedUp": {
+ "$ref": "#/components/messages/userSignedUp"
+ },
+ "userCompletedOrder": {
+ "$ref": "#/components/messages/userCompletedOrder"
+ }
+ },
+ "parameters": {
+ "userId": {
+ "$ref": "#/components/parameters/userId"
+ }
+ },
+ "servers": [
+ {
+ "$ref": "#/servers/rabbitmqInProd"
+ },
+ {
+ "$ref": "#/servers/rabbitmqInStaging"
+ }
+ ],
+ "bindings": {
+ "amqp": {
+ "is": "queue",
+ "queue": {
+ "exclusive": true
+ }
+ }
+ },
+ "tags": [
+ {
+ "name": "user",
+ "description": "User-related messages"
+ }
+ ],
+ "externalDocs": {
+ "description": "Find more info here",
+ "url": "https://example.com"
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/channelMessages.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/channelMessages.json",
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageObject.json"
+ }
+ ]
+ },
+ "description": "A map of the messages that will be sent to this channel by any application at any time. **Every message sent to this channel MUST be valid against one, and only one, of the message objects defined in this map.**"
+ },
+ "http://asyncapi.com/definitions/3.0.0/messageObject.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/messageObject.json",
+ "type": "object",
+ "description": "Describes a message received on a given channel and operation.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "contentType": {
+ "type": "string",
+ "description": "The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. application/json). When omitted, the value MUST be the one specified on the defaultContentType field."
+ },
+ "headers": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/anySchema.json"
+ },
+ "payload": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/anySchema.json"
+ },
+ "correlationId": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/correlationId.json"
+ }
+ ]
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/tag.json"
+ }
+ ]
+ },
+ "uniqueItems": true
+ },
+ "summary": {
+ "type": "string",
+ "description": "A brief summary of the message."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the message."
+ },
+ "title": {
+ "type": "string",
+ "description": "A human-friendly title for the message."
+ },
+ "description": {
+ "type": "string",
+ "description": "A longer description of the message. CommonMark is allowed."
+ },
+ "externalDocs": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ },
+ "deprecated": {
+ "type": "boolean",
+ "default": false
+ },
+ "examples": {
+ "type": "array",
+ "description": "List of examples.",
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageExampleObject.json"
+ }
+ },
+ "bindings": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageBindingsObject.json"
+ }
+ ]
+ },
+ "traits": {
+ "type": "array",
+ "description": "A list of traits to apply to the message object. Traits MUST be merged using traits merge mechanism. The resulting object MUST be a valid Message Object.",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageTrait.json"
+ },
+ {
+ "type": "array",
+ "items": [
+ {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageTrait.json"
+ }
+ ]
+ },
+ {
+ "type": "object",
+ "additionalItems": true
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "examples": [
+ {
+ "messageId": "userSignup",
+ "name": "UserSignup",
+ "title": "User signup",
+ "summary": "Action to sign a user up.",
+ "description": "A longer description",
+ "contentType": "application/json",
+ "tags": [
+ {
+ "name": "user"
+ },
+ {
+ "name": "signup"
+ },
+ {
+ "name": "register"
+ }
+ ],
+ "headers": {
+ "type": "object",
+ "properties": {
+ "correlationId": {
+ "description": "Correlation ID set by application",
+ "type": "string"
+ },
+ "applicationInstanceId": {
+ "description": "Unique identifier for a given instance of the publishing application",
+ "type": "string"
+ }
+ }
+ },
+ "payload": {
+ "type": "object",
+ "properties": {
+ "user": {
+ "$ref": "#/components/schemas/userCreate"
+ },
+ "signup": {
+ "$ref": "#/components/schemas/signup"
+ }
+ }
+ },
+ "correlationId": {
+ "description": "Default Correlation ID",
+ "location": "$message.header#/correlationId"
+ },
+ "traits": [
+ {
+ "$ref": "#/components/messageTraits/commonHeaders"
+ }
+ ],
+ "examples": [
+ {
+ "name": "SimpleSignup",
+ "summary": "A simple UserSignup example message",
+ "headers": {
+ "correlationId": "my-correlation-id",
+ "applicationInstanceId": "myInstanceId"
+ },
+ "payload": {
+ "user": {
+ "someUserKey": "someUserValue"
+ },
+ "signup": {
+ "someSignupKey": "someSignupValue"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/anySchema.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/anySchema.json",
+ "if": {
+ "required": [
+ "schema"
+ ]
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/multiFormatSchema.json"
+ },
+ "else": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ "description": "An object representing either a schema or a multiFormatSchema based on the existence of the 'schema' property. If the property 'schema' is present, use the multi-format schema. Use the default AsyncAPI Schema otherwise."
+ },
+ "http://asyncapi.com/definitions/3.0.0/multiFormatSchema.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/multiFormatSchema.json",
+ "description": "The Multi Format Schema Object represents a schema definition. It differs from the Schema Object in that it supports multiple schema formats or languages (e.g., JSON Schema, Avro, etc.).",
+ "type": "object",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "if": {
+ "not": {
+ "type": "object"
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ "else": {
+ "properties": {
+ "schemaFormat": {
+ "description": "A string containing the name of the schema format that is used to define the information. If schemaFormat is missing, it MUST default to application/vnd.aai.asyncapi+json;version={{asyncapi}} where {{asyncapi}} matches the AsyncAPI Version String. In such a case, this would make the Multi Format Schema Object equivalent to the Schema Object. When using Reference Object within the schema, the schemaFormat of the resource being referenced MUST match the schemaFormat of the schema that contains the initial reference. For example, if you reference Avro schema, then schemaFormat of referencing resource and the resource being reference MUST match.",
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "description": "All the schema formats tooling MUST support",
+ "enum": [
+ "application/schema+json;version=draft-07",
+ "application/schema+yaml;version=draft-07",
+ "application/vnd.aai.asyncapi;version=3.0.0",
+ "application/vnd.aai.asyncapi+json;version=3.0.0",
+ "application/vnd.aai.asyncapi+yaml;version=3.0.0"
+ ]
+ },
+ {
+ "description": "All the schema formats tools are RECOMMENDED to support",
+ "enum": [
+ "application/vnd.oai.openapi;version=3.0.0",
+ "application/vnd.oai.openapi+json;version=3.0.0",
+ "application/vnd.oai.openapi+yaml;version=3.0.0",
+ "application/vnd.apache.avro;version=1.9.0",
+ "application/vnd.apache.avro+json;version=1.9.0",
+ "application/vnd.apache.avro+yaml;version=1.9.0",
+ "application/raml+yaml;version=1.0"
+ ]
+ }
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "if": {
+ "not": {
+ "description": "If no schemaFormat has been defined, default to schema or reference",
+ "required": [
+ "schemaFormat"
+ ]
+ }
+ },
+ "then": {
+ "properties": {
+ "schema": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "description": "If schemaFormat has been defined check if it's one of the AsyncAPI Schema Object formats",
+ "required": [
+ "schemaFormat"
+ ],
+ "properties": {
+ "schemaFormat": {
+ "enum": [
+ "application/vnd.aai.asyncapi;version=2.0.0",
+ "application/vnd.aai.asyncapi+json;version=2.0.0",
+ "application/vnd.aai.asyncapi+yaml;version=2.0.0",
+ "application/vnd.aai.asyncapi;version=2.1.0",
+ "application/vnd.aai.asyncapi+json;version=2.1.0",
+ "application/vnd.aai.asyncapi+yaml;version=2.1.0",
+ "application/vnd.aai.asyncapi;version=2.2.0",
+ "application/vnd.aai.asyncapi+json;version=2.2.0",
+ "application/vnd.aai.asyncapi+yaml;version=2.2.0",
+ "application/vnd.aai.asyncapi;version=2.3.0",
+ "application/vnd.aai.asyncapi+json;version=2.3.0",
+ "application/vnd.aai.asyncapi+yaml;version=2.3.0",
+ "application/vnd.aai.asyncapi;version=2.4.0",
+ "application/vnd.aai.asyncapi+json;version=2.4.0",
+ "application/vnd.aai.asyncapi+yaml;version=2.4.0",
+ "application/vnd.aai.asyncapi;version=2.5.0",
+ "application/vnd.aai.asyncapi+json;version=2.5.0",
+ "application/vnd.aai.asyncapi+yaml;version=2.5.0",
+ "application/vnd.aai.asyncapi;version=2.6.0",
+ "application/vnd.aai.asyncapi+json;version=2.6.0",
+ "application/vnd.aai.asyncapi+yaml;version=2.6.0",
+ "application/vnd.aai.asyncapi;version=3.0.0",
+ "application/vnd.aai.asyncapi+json;version=3.0.0",
+ "application/vnd.aai.asyncapi+yaml;version=3.0.0"
+ ]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "schema": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "schemaFormat"
+ ],
+ "properties": {
+ "schemaFormat": {
+ "enum": [
+ "application/schema+json;version=draft-07",
+ "application/schema+yaml;version=draft-07"
+ ]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "schema": {
+ "$ref": "http://json-schema.org/draft-07/schema"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "schemaFormat"
+ ],
+ "properties": {
+ "schemaFormat": {
+ "enum": [
+ "application/vnd.oai.openapi;version=3.0.0",
+ "application/vnd.oai.openapi+json;version=3.0.0",
+ "application/vnd.oai.openapi+yaml;version=3.0.0"
+ ]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "schema": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/openapiSchema_3_0.json"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "schemaFormat"
+ ],
+ "properties": {
+ "schemaFormat": {
+ "enum": [
+ "application/vnd.apache.avro;version=1.9.0",
+ "application/vnd.apache.avro+json;version=1.9.0",
+ "application/vnd.apache.avro+yaml;version=1.9.0"
+ ]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "schema": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/avroSchema_v1.json"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "http://asyncapi.com/definitions/3.0.0/openapiSchema_3_0.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/openapiSchema_3_0.json",
+ "type": "object",
+ "definitions": {
+ "ExternalDocumentation": {
+ "type": "object",
+ "required": [
+ "url"
+ ],
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri-reference"
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ },
+ "additionalProperties": false
+ },
+ "Discriminator": {
+ "type": "object",
+ "required": [
+ "propertyName"
+ ],
+ "properties": {
+ "propertyName": {
+ "type": "string"
+ },
+ "mapping": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "Reference": {
+ "type": "object",
+ "required": [
+ "$ref"
+ ],
+ "patternProperties": {
+ "^\\$ref$": {
+ "type": "string",
+ "format": "uri-reference"
+ }
+ }
+ },
+ "XML": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "namespace": {
+ "type": "string",
+ "format": "uri"
+ },
+ "prefix": {
+ "type": "string"
+ },
+ "attribute": {
+ "type": "boolean",
+ "default": false
+ },
+ "wrapped": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "patternProperties": {
+ "^x-": {}
+ },
+ "additionalProperties": false
+ }
+ },
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "multipleOf": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "maximum": {
+ "type": "number"
+ },
+ "exclusiveMaximum": {
+ "type": "boolean",
+ "default": false
+ },
+ "minimum": {
+ "type": "number"
+ },
+ "exclusiveMinimum": {
+ "type": "boolean",
+ "default": false
+ },
+ "maxLength": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "minLength": {
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "pattern": {
+ "type": "string",
+ "format": "regex"
+ },
+ "maxItems": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "minItems": {
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "uniqueItems": {
+ "type": "boolean",
+ "default": false
+ },
+ "maxProperties": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "minProperties": {
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "required": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "minItems": 1,
+ "uniqueItems": true
+ },
+ "enum": {
+ "type": "array",
+ "items": true,
+ "minItems": 1,
+ "uniqueItems": false
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "array",
+ "boolean",
+ "integer",
+ "number",
+ "object",
+ "string"
+ ]
+ },
+ "not": {
+ "oneOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/Reference"
+ }
+ ]
+ },
+ "allOf": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/Reference"
+ }
+ ]
+ }
+ },
+ "oneOf": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/Reference"
+ }
+ ]
+ }
+ },
+ "anyOf": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/Reference"
+ }
+ ]
+ }
+ },
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/Reference"
+ }
+ ]
+ },
+ "properties": {
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/Reference"
+ }
+ ]
+ }
+ },
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "#"
+ },
+ {
+ "$ref": "#/definitions/Reference"
+ },
+ {
+ "type": "boolean"
+ }
+ ],
+ "default": true
+ },
+ "description": {
+ "type": "string"
+ },
+ "format": {
+ "type": "string"
+ },
+ "default": true,
+ "nullable": {
+ "type": "boolean",
+ "default": false
+ },
+ "discriminator": {
+ "$ref": "#/definitions/Discriminator"
+ },
+ "readOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "writeOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "example": true,
+ "externalDocs": {
+ "$ref": "#/definitions/ExternalDocumentation"
+ },
+ "deprecated": {
+ "type": "boolean",
+ "default": false
+ },
+ "xml": {
+ "$ref": "#/definitions/XML"
+ }
+ },
+ "patternProperties": {
+ "^x-": true
+ },
+ "additionalProperties": false
+ },
+ "http://asyncapi.com/definitions/3.0.0/avroSchema_v1.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/avroSchema_v1.json",
+ "definitions": {
+ "avroSchema": {
+ "title": "Avro Schema",
+ "description": "Root Schema",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/types"
+ }
+ ]
+ },
+ "types": {
+ "title": "Avro Types",
+ "description": "Allowed Avro types",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/primitiveType"
+ },
+ {
+ "$ref": "#/definitions/primitiveTypeWithMetadata"
+ },
+ {
+ "$ref": "#/definitions/customTypeReference"
+ },
+ {
+ "$ref": "#/definitions/avroRecord"
+ },
+ {
+ "$ref": "#/definitions/avroEnum"
+ },
+ {
+ "$ref": "#/definitions/avroArray"
+ },
+ {
+ "$ref": "#/definitions/avroMap"
+ },
+ {
+ "$ref": "#/definitions/avroFixed"
+ },
+ {
+ "$ref": "#/definitions/avroUnion"
+ }
+ ]
+ },
+ "primitiveType": {
+ "title": "Primitive Type",
+ "description": "Basic type primitives.",
+ "type": "string",
+ "enum": [
+ "null",
+ "boolean",
+ "int",
+ "long",
+ "float",
+ "double",
+ "bytes",
+ "string"
+ ]
+ },
+ "primitiveTypeWithMetadata": {
+ "title": "Primitive Type With Metadata",
+ "description": "A primitive type with metadata attached.",
+ "type": "object",
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/primitiveType"
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "customTypeReference": {
+ "title": "Custom Type",
+ "description": "Reference to a ComplexType",
+ "not": {
+ "$ref": "#/definitions/primitiveType"
+ },
+ "type": "string",
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$"
+ },
+ "avroUnion": {
+ "title": "Union",
+ "description": "A Union of types",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/avroSchema"
+ },
+ "minItems": 1
+ },
+ "avroField": {
+ "title": "Field",
+ "description": "A field within a Record",
+ "type": "object",
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/name"
+ },
+ "type": {
+ "$ref": "#/definitions/types"
+ },
+ "doc": {
+ "type": "string"
+ },
+ "default": true,
+ "order": {
+ "enum": [
+ "ascending",
+ "descending",
+ "ignore"
+ ]
+ },
+ "aliases": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/name"
+ }
+ }
+ },
+ "required": [
+ "name",
+ "type"
+ ]
+ },
+ "avroRecord": {
+ "title": "Record",
+ "description": "A Record",
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "const": "record"
+ },
+ "name": {
+ "$ref": "#/definitions/name"
+ },
+ "namespace": {
+ "$ref": "#/definitions/namespace"
+ },
+ "doc": {
+ "type": "string"
+ },
+ "aliases": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/name"
+ }
+ },
+ "fields": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/avroField"
+ }
+ }
+ },
+ "required": [
+ "type",
+ "name",
+ "fields"
+ ]
+ },
+ "avroEnum": {
+ "title": "Enum",
+ "description": "An enumeration",
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "const": "enum"
+ },
+ "name": {
+ "$ref": "#/definitions/name"
+ },
+ "namespace": {
+ "$ref": "#/definitions/namespace"
+ },
+ "doc": {
+ "type": "string"
+ },
+ "aliases": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/name"
+ }
+ },
+ "symbols": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/name"
+ }
+ }
+ },
+ "required": [
+ "type",
+ "name",
+ "symbols"
+ ]
+ },
+ "avroArray": {
+ "title": "Array",
+ "description": "An array",
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "const": "array"
+ },
+ "name": {
+ "$ref": "#/definitions/name"
+ },
+ "namespace": {
+ "$ref": "#/definitions/namespace"
+ },
+ "doc": {
+ "type": "string"
+ },
+ "aliases": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/name"
+ }
+ },
+ "items": {
+ "$ref": "#/definitions/types"
+ }
+ },
+ "required": [
+ "type",
+ "items"
+ ]
+ },
+ "avroMap": {
+ "title": "Map",
+ "description": "A map of values",
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "const": "map"
+ },
+ "name": {
+ "$ref": "#/definitions/name"
+ },
+ "namespace": {
+ "$ref": "#/definitions/namespace"
+ },
+ "doc": {
+ "type": "string"
+ },
+ "aliases": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/name"
+ }
+ },
+ "values": {
+ "$ref": "#/definitions/types"
+ }
+ },
+ "required": [
+ "type",
+ "values"
+ ]
+ },
+ "avroFixed": {
+ "title": "Fixed",
+ "description": "A fixed sized array of bytes",
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "const": "fixed"
+ },
+ "name": {
+ "$ref": "#/definitions/name"
+ },
+ "namespace": {
+ "$ref": "#/definitions/namespace"
+ },
+ "doc": {
+ "type": "string"
+ },
+ "aliases": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/name"
+ }
+ },
+ "size": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "type",
+ "name",
+ "size"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
+ },
+ "namespace": {
+ "type": "string",
+ "pattern": "^([A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*)*$"
+ }
+ },
+ "description": "Json-Schema definition for Avro AVSC files.",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/avroSchema"
+ }
+ ],
+ "title": "Avro Schema Definition"
+ },
+ "http://asyncapi.com/definitions/3.0.0/correlationId.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/correlationId.json",
+ "type": "object",
+ "description": "An object that specifies an identifier at design time that can used for message tracing and correlation.",
+ "required": [
+ "location"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "description": {
+ "type": "string",
+ "description": "A optional description of the correlation ID. GitHub Flavored Markdown is allowed."
+ },
+ "location": {
+ "type": "string",
+ "description": "A runtime expression that specifies the location of the correlation ID",
+ "pattern": "^\\$message\\.(header|payload)#(\\/(([^\\/~])|(~[01]))*)*"
+ }
+ },
+ "examples": [
+ {
+ "description": "Default Correlation ID",
+ "location": "$message.header#/correlationId"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/messageExampleObject.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/messageExampleObject.json",
+ "type": "object",
+ "additionalProperties": false,
+ "anyOf": [
+ {
+ "required": [
+ "payload"
+ ]
+ },
+ {
+ "required": [
+ "headers"
+ ]
+ }
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Machine readable name of the message example."
+ },
+ "summary": {
+ "type": "string",
+ "description": "A brief summary of the message example."
+ },
+ "headers": {
+ "type": "object",
+ "description": "Example of the application headers. It MUST be a map of key-value pairs."
+ },
+ "payload": {
+ "type": [
+ "number",
+ "string",
+ "boolean",
+ "object",
+ "array",
+ "null"
+ ],
+ "description": "Example of the message payload. It can be of any type."
+ }
+ }
+ },
+ "http://asyncapi.com/definitions/3.0.0/messageBindingsObject.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/messageBindingsObject.json",
+ "type": "object",
+ "description": "Map describing protocol-specific definitions for a message.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "http": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0",
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/http/0.3.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/http/0.2.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/http/0.3.0/message.json"
+ }
+ }
+ ]
+ },
+ "ws": {},
+ "amqp": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/amqp/0.3.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/amqp/0.3.0/message.json"
+ }
+ }
+ ]
+ },
+ "amqp1": {},
+ "mqtt": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/mqtt/0.2.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/mqtt/0.2.0/message.json"
+ }
+ }
+ ]
+ },
+ "kafka": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.5.0",
+ "0.4.0",
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.5.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.5.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.5.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.4.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.4.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.3.0/message.json"
+ }
+ }
+ ]
+ },
+ "anypointmq": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.0.1"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/anypointmq/0.0.1/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.0.1"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/anypointmq/0.0.1/message.json"
+ }
+ }
+ ]
+ },
+ "nats": {},
+ "jms": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.0.1"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/jms/0.0.1/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.0.1"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/jms/0.0.1/message.json"
+ }
+ }
+ ]
+ },
+ "sns": {},
+ "sqs": {},
+ "stomp": {},
+ "redis": {},
+ "ibmmq": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/ibmmq/0.1.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/ibmmq/0.1.0/message.json"
+ }
+ }
+ ]
+ },
+ "solace": {},
+ "googlepubsub": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/googlepubsub/0.2.0/message.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/googlepubsub/0.2.0/message.json"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "http://asyncapi.com/bindings/http/0.3.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/http/0.3.0/message.json",
+ "title": "HTTP message bindings object",
+ "description": "This object contains information about the message representation in HTTP.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "headers": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "\tA Schema object containing the definitions for HTTP-specific headers. This schema MUST be of type 'object' and have a 'properties' key."
+ },
+ "statusCode": {
+ "type": "number",
+ "description": "The HTTP response status code according to [RFC 9110](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes). `statusCode` is only relevant for messages referenced by the [Operation Reply Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#operationReplyObject), as it defines the status code for the response. In all other cases, this value can be safely ignored."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, \"latest\" MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "headers": {
+ "type": "object",
+ "properties": {
+ "Content-Type": {
+ "type": "string",
+ "enum": [
+ "application/json"
+ ]
+ }
+ }
+ },
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/http/0.2.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/http/0.2.0/message.json",
+ "title": "HTTP message bindings object",
+ "description": "This object contains information about the message representation in HTTP.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "headers": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "\tA Schema object containing the definitions for HTTP-specific headers. This schema MUST be of type 'object' and have a 'properties' key."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding. If omitted, \"latest\" MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "headers": {
+ "type": "object",
+ "properties": {
+ "Content-Type": {
+ "type": "string",
+ "enum": [
+ "application/json"
+ ]
+ }
+ }
+ },
+ "bindingVersion": "0.2.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/amqp/0.3.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/amqp/0.3.0/message.json",
+ "title": "AMQP message bindings object",
+ "description": "This object contains information about the message representation in AMQP.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "contentEncoding": {
+ "type": "string",
+ "description": "A MIME encoding for the message content."
+ },
+ "messageType": {
+ "type": "string",
+ "description": "Application-specific message type."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, \"latest\" MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "contentEncoding": "gzip",
+ "messageType": "user.signup",
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/mqtt/0.2.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/mqtt/0.2.0/message.json",
+ "title": "MQTT message bindings object",
+ "description": "This object contains information about the message representation in MQTT.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "payloadFormatIndicator": {
+ "type": "integer",
+ "enum": [
+ 0,
+ 1
+ ],
+ "description": "1 indicates that the payload is UTF-8 encoded character data. 0 indicates that the payload format is unspecified.",
+ "default": 0
+ },
+ "correlationData": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ ],
+ "description": "Correlation Data is used by the sender of the request message to identify which request the response message is for when it is received."
+ },
+ "contentType": {
+ "type": "string",
+ "description": "String describing the content type of the message payload. This should not conflict with the contentType field of the associated AsyncAPI Message object."
+ },
+ "responseTopic": {
+ "oneOf": [
+ {
+ "type": "string",
+ "format": "uri-template",
+ "minLength": 1
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ ],
+ "description": "The topic (channel URI) to be used for a response message."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "bindingVersion": "0.2.0"
+ },
+ {
+ "contentType": "application/json",
+ "correlationData": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "responseTopic": "application/responses",
+ "bindingVersion": "0.2.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.5.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.5.0/message.json",
+ "title": "Message Schema",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "key": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ }
+ ],
+ "description": "The message key."
+ },
+ "schemaIdLocation": {
+ "type": "string",
+ "description": "If a Schema Registry is used when performing this operation, tells where the id of schema is stored.",
+ "enum": [
+ "header",
+ "payload"
+ ]
+ },
+ "schemaIdPayloadEncoding": {
+ "type": "string",
+ "description": "Number of bytes or vendor specific values when schema id is encoded in payload."
+ },
+ "schemaLookupStrategy": {
+ "type": "string",
+ "description": "Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.5.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "key": {
+ "type": "string",
+ "enum": [
+ "myKey"
+ ]
+ },
+ "schemaIdLocation": "payload",
+ "schemaIdPayloadEncoding": "apicurio-new",
+ "schemaLookupStrategy": "TopicIdStrategy",
+ "bindingVersion": "0.5.0"
+ },
+ {
+ "key": {
+ "$ref": "path/to/user-create.avsc#/UserCreate"
+ },
+ "schemaIdLocation": "payload",
+ "schemaIdPayloadEncoding": "4",
+ "bindingVersion": "0.5.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.4.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.4.0/message.json",
+ "title": "Message Schema",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "key": {
+ "anyOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/avroSchema_v1.json"
+ }
+ ],
+ "description": "The message key."
+ },
+ "schemaIdLocation": {
+ "type": "string",
+ "description": "If a Schema Registry is used when performing this operation, tells where the id of schema is stored.",
+ "enum": [
+ "header",
+ "payload"
+ ]
+ },
+ "schemaIdPayloadEncoding": {
+ "type": "string",
+ "description": "Number of bytes or vendor specific values when schema id is encoded in payload."
+ },
+ "schemaLookupStrategy": {
+ "type": "string",
+ "description": "Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.4.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "key": {
+ "type": "string",
+ "enum": [
+ "myKey"
+ ]
+ },
+ "schemaIdLocation": "payload",
+ "schemaIdPayloadEncoding": "apicurio-new",
+ "schemaLookupStrategy": "TopicIdStrategy",
+ "bindingVersion": "0.4.0"
+ },
+ {
+ "key": {
+ "$ref": "path/to/user-create.avsc#/UserCreate"
+ },
+ "schemaIdLocation": "payload",
+ "schemaIdPayloadEncoding": "4",
+ "bindingVersion": "0.4.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.3.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.3.0/message.json",
+ "title": "Message Schema",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "key": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "The message key."
+ },
+ "schemaIdLocation": {
+ "type": "string",
+ "description": "If a Schema Registry is used when performing this operation, tells where the id of schema is stored.",
+ "enum": [
+ "header",
+ "payload"
+ ]
+ },
+ "schemaIdPayloadEncoding": {
+ "type": "string",
+ "description": "Number of bytes or vendor specific values when schema id is encoded in payload."
+ },
+ "schemaLookupStrategy": {
+ "type": "string",
+ "description": "Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "key": {
+ "type": "string",
+ "enum": [
+ "myKey"
+ ]
+ },
+ "schemaIdLocation": "payload",
+ "schemaIdPayloadEncoding": "apicurio-new",
+ "schemaLookupStrategy": "TopicIdStrategy",
+ "bindingVersion": "0.3.0"
+ },
+ {
+ "key": {
+ "$ref": "path/to/user-create.avsc#/UserCreate"
+ },
+ "schemaIdLocation": "payload",
+ "schemaIdPayloadEncoding": "4",
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/anypointmq/0.0.1/message.json": {
+ "$id": "http://asyncapi.com/bindings/anypointmq/0.0.1/message.json",
+ "title": "Anypoint MQ message bindings object",
+ "description": "This object contains configuration for describing an Anypoint MQ message as an AsyncAPI message. This objects only contains configuration that can not be provided in the AsyncAPI standard message object.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "headers": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ ],
+ "description": "A Schema object containing the definitions for Anypoint MQ-specific headers (protocol headers). This schema MUST be of type 'object' and have a 'properties' key. Examples of Anypoint MQ protocol headers are 'messageId' and 'messageGroupId'."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.0.1"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "headers": {
+ "type": "object",
+ "properties": {
+ "messageId": {
+ "type": "string"
+ }
+ }
+ },
+ "bindingVersion": "0.0.1"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/jms/0.0.1/message.json": {
+ "$id": "http://asyncapi.com/bindings/jms/0.0.1/message.json",
+ "title": "Message Schema",
+ "description": "This object contains configuration for describing a JMS message as an AsyncAPI message. This objects only contains configuration that can not be provided in the AsyncAPI standard message object.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "headers": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "A Schema object containing the definitions for JMS headers (protocol headers). This schema MUST be of type 'object' and have a 'properties' key. Examples of JMS protocol headers are 'JMSMessageID', 'JMSTimestamp', and 'JMSCorrelationID'."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.0.1"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "headers": {
+ "type": "object",
+ "required": [
+ "JMSMessageID"
+ ],
+ "properties": {
+ "JMSMessageID": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "A unique message identifier. This may be set by your JMS Provider on your behalf."
+ },
+ "JMSTimestamp": {
+ "type": "integer",
+ "description": "The time the message was sent. This may be set by your JMS Provider on your behalf. The time the message was sent. The value of the timestamp is the amount of time, measured in milliseconds, that has elapsed since midnight, January 1, 1970, UTC."
+ },
+ "JMSDeliveryMode": {
+ "type": "string",
+ "enum": [
+ "PERSISTENT",
+ "NON_PERSISTENT"
+ ],
+ "default": "PERSISTENT",
+ "description": "Denotes the delivery mode for the message. This may be set by your JMS Provider on your behalf."
+ },
+ "JMSPriority": {
+ "type": "integer",
+ "default": 4,
+ "description": "The priority of the message. This may be set by your JMS Provider on your behalf."
+ },
+ "JMSExpires": {
+ "type": "integer",
+ "description": "The time at which the message expires. This may be set by your JMS Provider on your behalf. A value of zero means that the message does not expire. Any non-zero value is the amount of time, measured in milliseconds, that has elapsed since midnight, January 1, 1970, UTC, at which the message will expire."
+ },
+ "JMSType": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The type of message. Some JMS providers use a message repository that contains the definitions of messages sent by applications. The 'JMSType' header field may reference a message's definition in the provider's repository. The JMS API does not define a standard message definition repository, nor does it define a naming policy for the definitions it contains. Some messaging systems require that a message type definition for each application message be created and that each message specify its type. In order to work with such JMS providers, JMS clients should assign a value to 'JMSType', whether the application makes use of it or not. This ensures that the field is properly set for those providers that require it."
+ },
+ "JMSCorrelationID": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The correlation identifier of the message. A client can use the 'JMSCorrelationID' header field to link one message with another. A typical use is to link a response message with its request message. Since each message sent by a JMS provider is assigned a message ID value, it is convenient to link messages via message ID, such message ID values must start with the 'ID:' prefix. Conversely, application-specified values must not start with the 'ID:' prefix; this is reserved for provider-generated message ID values."
+ },
+ "JMSReplyTo": {
+ "type": "string",
+ "description": "The queue or topic that the message sender expects replies to."
+ }
+ }
+ },
+ "bindingVersion": "0.0.1"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/ibmmq/0.1.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/ibmmq/0.1.0/message.json",
+ "title": "IBM MQ message bindings object",
+ "description": "This object contains information about the message representation in IBM MQ.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "string",
+ "jms",
+ "binary"
+ ],
+ "default": "string",
+ "description": "The type of the message."
+ },
+ "headers": {
+ "type": "string",
+ "description": "Defines the IBM MQ message headers to include with this message. More than one header can be specified as a comma separated list. Supporting information on IBM MQ message formats can be found on this [page](https://www.ibm.com/docs/en/ibm-mq/9.2?topic=mqmd-format-mqchar8) in the IBM MQ Knowledge Center."
+ },
+ "description": {
+ "type": "string",
+ "description": "Provides additional information for application developers: describes the message type or format."
+ },
+ "expiry": {
+ "type": "integer",
+ "minimum": 0,
+ "default": 0,
+ "description": "The recommended setting the client should use for the TTL (Time-To-Live) of the message. This is a period of time expressed in milliseconds and set by the application that puts the message. 'expiry' values are API dependant e.g., MQI and JMS use different units of time and default values for 'unlimited'. General information on IBM MQ message expiry can be found on this [page](https://www.ibm.com/docs/en/ibm-mq/9.2?topic=mqmd-expiry-mqlong) in the IBM MQ Knowledge Center."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "type": {
+ "const": "binary"
+ }
+ }
+ },
+ {
+ "properties": {
+ "type": {
+ "const": "jms"
+ }
+ },
+ "not": {
+ "required": [
+ "headers"
+ ]
+ }
+ },
+ {
+ "properties": {
+ "type": {
+ "const": "string"
+ }
+ },
+ "not": {
+ "required": [
+ "headers"
+ ]
+ }
+ }
+ ],
+ "examples": [
+ {
+ "type": "string",
+ "bindingVersion": "0.1.0"
+ },
+ {
+ "type": "jms",
+ "description": "JMS stream message",
+ "bindingVersion": "0.1.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/googlepubsub/0.2.0/message.json": {
+ "$id": "http://asyncapi.com/bindings/googlepubsub/0.2.0/message.json",
+ "title": "Cloud Pub/Sub Channel Schema",
+ "description": "This object contains information about the message representation for Google Cloud Pub/Sub.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding."
+ },
+ "attributes": {
+ "type": "object"
+ },
+ "orderingKey": {
+ "type": "string"
+ },
+ "schema": {
+ "type": "object",
+ "additionalItems": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+ "examples": [
+ {
+ "schema": {
+ "name": "projects/your-project-id/schemas/your-avro-schema-id"
+ }
+ },
+ {
+ "schema": {
+ "name": "projects/your-project-id/schemas/your-protobuf-schema-id"
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/messageTrait.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/messageTrait.json",
+ "type": "object",
+ "description": "Describes a trait that MAY be applied to a Message Object. This object MAY contain any property from the Message Object, except payload and traits.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "contentType": {
+ "type": "string",
+ "description": "The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. application/json). When omitted, the value MUST be the one specified on the defaultContentType field."
+ },
+ "headers": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/anySchema.json"
+ },
+ "correlationId": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/correlationId.json"
+ }
+ ]
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/tag.json"
+ }
+ ]
+ },
+ "uniqueItems": true
+ },
+ "summary": {
+ "type": "string",
+ "description": "A brief summary of the message."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the message."
+ },
+ "title": {
+ "type": "string",
+ "description": "A human-friendly title for the message."
+ },
+ "description": {
+ "type": "string",
+ "description": "A longer description of the message. CommonMark is allowed."
+ },
+ "externalDocs": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ },
+ "deprecated": {
+ "type": "boolean",
+ "default": false
+ },
+ "examples": {
+ "type": "array",
+ "description": "List of examples.",
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageExampleObject.json"
+ }
+ },
+ "bindings": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageBindingsObject.json"
+ }
+ ]
+ }
+ },
+ "examples": [
+ {
+ "contentType": "application/json"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/parameters.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/parameters.json",
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/parameter.json"
+ }
+ ]
+ },
+ "description": "JSON objects describing re-usable channel parameters.",
+ "examples": [
+ {
+ "address": "user/{userId}/signedup",
+ "parameters": {
+ "userId": {
+ "description": "Id of the user."
+ }
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/parameter.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/parameter.json",
+ "description": "Describes a parameter included in a channel address.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "description": {
+ "type": "string",
+ "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed."
+ },
+ "enum": {
+ "description": "An enumeration of string values to be used if the substitution options are from a limited set.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "default": {
+ "description": "The default value to use for substitution, and to send, if an alternate value is not supplied.",
+ "type": "string"
+ },
+ "examples": {
+ "description": "An array of examples of the parameter value.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "location": {
+ "type": "string",
+ "description": "A runtime expression that specifies the location of the parameter value",
+ "pattern": "^\\$message\\.(header|payload)#(\\/(([^\\/~])|(~[01]))*)*"
+ }
+ },
+ "examples": [
+ {
+ "address": "user/{userId}/signedup",
+ "parameters": {
+ "userId": {
+ "description": "Id of the user.",
+ "location": "$message.payload#/user/id"
+ }
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/channelBindingsObject.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/channelBindingsObject.json",
+ "type": "object",
+ "description": "Map describing protocol-specific definitions for a channel.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "http": {},
+ "ws": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/websockets/0.1.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/websockets/0.1.0/channel.json"
+ }
+ }
+ ]
+ },
+ "amqp": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/amqp/0.3.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/amqp/0.3.0/channel.json"
+ }
+ }
+ ]
+ },
+ "amqp1": {},
+ "mqtt": {},
+ "kafka": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.5.0",
+ "0.4.0",
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.5.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.5.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.5.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.4.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.4.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.3.0/channel.json"
+ }
+ }
+ ]
+ },
+ "anypointmq": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.0.1"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/anypointmq/0.0.1/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.0.1"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/anypointmq/0.0.1/channel.json"
+ }
+ }
+ ]
+ },
+ "nats": {},
+ "jms": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.0.1"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/jms/0.0.1/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.0.1"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/jms/0.0.1/channel.json"
+ }
+ }
+ ]
+ },
+ "sns": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/channel.json"
+ }
+ }
+ ]
+ },
+ "sqs": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json"
+ }
+ }
+ ]
+ },
+ "stomp": {},
+ "redis": {},
+ "ibmmq": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/ibmmq/0.1.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/ibmmq/0.1.0/channel.json"
+ }
+ }
+ ]
+ },
+ "solace": {},
+ "googlepubsub": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/googlepubsub/0.2.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/googlepubsub/0.2.0/channel.json"
+ }
+ }
+ ]
+ },
+ "pulsar": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/pulsar/0.1.0/channel.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/pulsar/0.1.0/channel.json"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "http://asyncapi.com/bindings/websockets/0.1.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/websockets/0.1.0/channel.json",
+ "title": "WebSockets channel bindings object",
+ "description": "When using WebSockets, the channel represents the connection. Unlike other protocols that support multiple virtual channels (topics, routing keys, etc.) per connection, WebSockets doesn't support virtual channels or, put it another way, there's only one channel and its characteristics are strongly related to the protocol used for the handshake, i.e., HTTP.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "GET",
+ "POST"
+ ],
+ "description": "The HTTP method to use when establishing the connection. Its value MUST be either 'GET' or 'POST'."
+ },
+ "query": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ ],
+ "description": "A Schema object containing the definitions for each query parameter. This schema MUST be of type 'object' and have a 'properties' key."
+ },
+ "headers": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ ],
+ "description": "A Schema object containing the definitions of the HTTP headers to use when establishing the connection. This schema MUST be of type 'object' and have a 'properties' key."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "method": "POST",
+ "bindingVersion": "0.1.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/amqp/0.3.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/amqp/0.3.0/channel.json",
+ "title": "AMQP channel bindings object",
+ "description": "This object contains information about the channel representation in AMQP.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "is": {
+ "type": "string",
+ "enum": [
+ "queue",
+ "routingKey"
+ ],
+ "description": "Defines what type of channel is it. Can be either 'queue' or 'routingKey' (default)."
+ },
+ "exchange": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the exchange. It MUST NOT exceed 255 characters long."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "topic",
+ "direct",
+ "fanout",
+ "default",
+ "headers"
+ ],
+ "description": "The type of the exchange. Can be either 'topic', 'direct', 'fanout', 'default' or 'headers'."
+ },
+ "durable": {
+ "type": "boolean",
+ "description": "Whether the exchange should survive broker restarts or not."
+ },
+ "autoDelete": {
+ "type": "boolean",
+ "description": "Whether the exchange should be deleted when the last queue is unbound from it."
+ },
+ "vhost": {
+ "type": "string",
+ "default": "/",
+ "description": "The virtual host of the exchange. Defaults to '/'."
+ }
+ },
+ "description": "When is=routingKey, this object defines the exchange properties."
+ },
+ "queue": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "maxLength": 255,
+ "description": "The name of the queue. It MUST NOT exceed 255 characters long."
+ },
+ "durable": {
+ "type": "boolean",
+ "description": "Whether the queue should survive broker restarts or not."
+ },
+ "exclusive": {
+ "type": "boolean",
+ "description": "Whether the queue should be used only by one connection or not."
+ },
+ "autoDelete": {
+ "type": "boolean",
+ "description": "Whether the queue should be deleted when the last consumer unsubscribes."
+ },
+ "vhost": {
+ "type": "string",
+ "default": "/",
+ "description": "The virtual host of the queue. Defaults to '/'."
+ }
+ },
+ "description": "When is=queue, this object defines the queue properties."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "is": {
+ "const": "routingKey"
+ }
+ },
+ "required": [
+ "exchange"
+ ],
+ "not": {
+ "required": [
+ "queue"
+ ]
+ }
+ },
+ {
+ "properties": {
+ "is": {
+ "const": "queue"
+ }
+ },
+ "required": [
+ "queue"
+ ],
+ "not": {
+ "required": [
+ "exchange"
+ ]
+ }
+ }
+ ],
+ "examples": [
+ {
+ "is": "routingKey",
+ "exchange": {
+ "name": "myExchange",
+ "type": "topic",
+ "durable": true,
+ "autoDelete": false,
+ "vhost": "/"
+ },
+ "bindingVersion": "0.3.0"
+ },
+ {
+ "is": "queue",
+ "queue": {
+ "name": "my-queue-name",
+ "durable": true,
+ "exclusive": true,
+ "autoDelete": false,
+ "vhost": "/"
+ },
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.5.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.5.0/channel.json",
+ "title": "Channel Schema",
+ "description": "This object contains information about the channel representation in Kafka.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "topic": {
+ "type": "string",
+ "description": "Kafka topic name if different from channel name."
+ },
+ "partitions": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Number of partitions configured on this topic."
+ },
+ "replicas": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Number of replicas configured on this topic."
+ },
+ "topicConfiguration": {
+ "description": "Topic configuration properties that are relevant for the API.",
+ "type": "object",
+ "additionalProperties": true,
+ "properties": {
+ "cleanup.policy": {
+ "description": "The [`cleanup.policy`](https://kafka.apache.org/documentation/#topicconfigs_cleanup.policy) configuration option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "compact",
+ "delete"
+ ]
+ }
+ },
+ "retention.ms": {
+ "description": "The [`retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_retention.ms) configuration option.",
+ "type": "integer",
+ "minimum": -1
+ },
+ "retention.bytes": {
+ "description": "The [`retention.bytes`](https://kafka.apache.org/documentation/#topicconfigs_retention.bytes) configuration option.",
+ "type": "integer",
+ "minimum": -1
+ },
+ "delete.retention.ms": {
+ "description": "The [`delete.retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_delete.retention.ms) configuration option.",
+ "type": "integer",
+ "minimum": 0
+ },
+ "max.message.bytes": {
+ "description": "The [`max.message.bytes`](https://kafka.apache.org/documentation/#topicconfigs_max.message.bytes) configuration option.",
+ "type": "integer",
+ "minimum": 0
+ },
+ "confluent.key.schema.validation": {
+ "description": "It shows whether the schema validation for the message key is enabled. Vendor specific config. For more details: (https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#confluent-key-schema-validation)",
+ "type": "boolean"
+ },
+ "confluent.key.subject.name.strategy": {
+ "description": "The name of the schema lookup strategy for the message key. Vendor specific config. For more details: (https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#confluent-key-subject-name-strategy)",
+ "type": "string"
+ },
+ "confluent.value.schema.validation": {
+ "description": "It shows whether the schema validation for the message value is enabled. Vendor specific config. For more details: (https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#confluent-value-schema-validation)",
+ "type": "boolean"
+ },
+ "confluent.value.subject.name.strategy": {
+ "description": "The name of the schema lookup strategy for the message value. Vendor specific config. For more details: (https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#confluent-value-subject-name-strategy)",
+ "type": "string"
+ }
+ }
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.5.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "topic": "my-specific-topic",
+ "partitions": 20,
+ "replicas": 3,
+ "bindingVersion": "0.5.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.4.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.4.0/channel.json",
+ "title": "Channel Schema",
+ "description": "This object contains information about the channel representation in Kafka.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "topic": {
+ "type": "string",
+ "description": "Kafka topic name if different from channel name."
+ },
+ "partitions": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Number of partitions configured on this topic."
+ },
+ "replicas": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Number of replicas configured on this topic."
+ },
+ "topicConfiguration": {
+ "description": "Topic configuration properties that are relevant for the API.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "cleanup.policy": {
+ "description": "The [`cleanup.policy`](https://kafka.apache.org/documentation/#topicconfigs_cleanup.policy) configuration option.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "compact",
+ "delete"
+ ]
+ }
+ },
+ "retention.ms": {
+ "description": "The [`retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_retention.ms) configuration option.",
+ "type": "integer",
+ "minimum": -1
+ },
+ "retention.bytes": {
+ "description": "The [`retention.bytes`](https://kafka.apache.org/documentation/#topicconfigs_retention.bytes) configuration option.",
+ "type": "integer",
+ "minimum": -1
+ },
+ "delete.retention.ms": {
+ "description": "The [`delete.retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_delete.retention.ms) configuration option.",
+ "type": "integer",
+ "minimum": 0
+ },
+ "max.message.bytes": {
+ "description": "The [`max.message.bytes`](https://kafka.apache.org/documentation/#topicconfigs_max.message.bytes) configuration option.",
+ "type": "integer",
+ "minimum": 0
+ }
+ }
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.4.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "topic": "my-specific-topic",
+ "partitions": 20,
+ "replicas": 3,
+ "bindingVersion": "0.4.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.3.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.3.0/channel.json",
+ "title": "Channel Schema",
+ "description": "This object contains information about the channel representation in Kafka.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "topic": {
+ "type": "string",
+ "description": "Kafka topic name if different from channel name."
+ },
+ "partitions": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Number of partitions configured on this topic."
+ },
+ "replicas": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Number of replicas configured on this topic."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "topic": "my-specific-topic",
+ "partitions": 20,
+ "replicas": 3,
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/anypointmq/0.0.1/channel.json": {
+ "$id": "http://asyncapi.com/bindings/anypointmq/0.0.1/channel.json",
+ "title": "Anypoint MQ channel bindings object",
+ "description": "This object contains configuration for describing an Anypoint MQ exchange, queue, or FIFO queue as an AsyncAPI channel. This objects only contains configuration that can not be provided in the AsyncAPI standard channel object.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "destination": {
+ "type": "string",
+ "description": "The destination (queue or exchange) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name in Anypoint MQ. Defaults to the channel name."
+ },
+ "destinationType": {
+ "type": "string",
+ "enum": [
+ "exchange",
+ "queue",
+ "fifo-queue"
+ ],
+ "default": "queue",
+ "description": "The type of destination. SHOULD be specified to document the messaging model (publish/subscribe, point-to-point, strict message ordering) supported by this channel."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.0.1"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "destination": "user-signup-exchg",
+ "destinationType": "exchange",
+ "bindingVersion": "0.0.1"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/jms/0.0.1/channel.json": {
+ "$id": "http://asyncapi.com/bindings/jms/0.0.1/channel.json",
+ "title": "Channel Schema",
+ "description": "This object contains configuration for describing a JMS queue, or FIFO queue as an AsyncAPI channel. This objects only contains configuration that can not be provided in the AsyncAPI standard channel object.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "destination": {
+ "type": "string",
+ "description": "The destination (queue) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name according to the JMS Provider. Defaults to the channel name."
+ },
+ "destinationType": {
+ "type": "string",
+ "enum": [
+ "queue",
+ "fifo-queue"
+ ],
+ "default": "queue",
+ "description": "The type of destination. SHOULD be specified to document the messaging model (point-to-point, or strict message ordering) supported by this channel."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.0.1"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "destination": "user-signed-up",
+ "destinationType": "fifo-queue",
+ "bindingVersion": "0.0.1"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/sns/0.1.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/sns/0.1.0/channel.json",
+ "title": "Channel Schema",
+ "description": "This object contains information about the channel representation in SNS.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the topic. Can be different from the channel name to allow flexibility around AWS resource naming limitations."
+ },
+ "ordering": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/channel.json#/definitions/ordering"
+ },
+ "policy": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/channel.json#/definitions/policy"
+ },
+ "tags": {
+ "type": "object",
+ "description": "Key-value pairs that represent AWS tags on the topic."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "description": "The version of this binding.",
+ "default": "latest"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "definitions": {
+ "ordering": {
+ "type": "object",
+ "description": "By default, we assume an unordered SNS topic. This field allows configuration of a FIFO SNS Topic.",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Defines the type of SNS Topic.",
+ "enum": [
+ "standard",
+ "FIFO"
+ ]
+ },
+ "contentBasedDeduplication": {
+ "type": "boolean",
+ "description": "True to turn on de-duplication of messages for a channel."
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "policy": {
+ "type": "object",
+ "description": "The security policy for the SNS Topic.",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "statements": {
+ "type": "array",
+ "description": "An array of statement objects, each of which controls a permission for this topic",
+ "items": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/channel.json#/definitions/statement"
+ }
+ }
+ },
+ "required": [
+ "statements"
+ ]
+ },
+ "statement": {
+ "type": "object",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "effect": {
+ "type": "string",
+ "enum": [
+ "Allow",
+ "Deny"
+ ]
+ },
+ "principal": {
+ "description": "The AWS account or resource ARN that this statement applies to.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "action": {
+ "description": "The SNS permission being allowed or denied e.g. sns:Publish",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ }
+ },
+ "required": [
+ "effect",
+ "principal",
+ "action"
+ ]
+ }
+ },
+ "examples": [
+ {
+ "name": "my-sns-topic",
+ "policy": {
+ "statements": [
+ {
+ "effect": "Allow",
+ "principal": "*",
+ "action": "SNS:Publish"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/sqs/0.2.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json",
+ "title": "Channel Schema",
+ "description": "This object contains information about the channel representation in SQS.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "queue": {
+ "description": "A definition of the queue that will be used as the channel.",
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json#/definitions/queue"
+ },
+ "deadLetterQueue": {
+ "description": "A definition of the queue that will be used for un-processable messages.",
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json#/definitions/queue"
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0",
+ "0.2.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed.",
+ "default": "latest"
+ }
+ },
+ "required": [
+ "queue"
+ ],
+ "definitions": {
+ "queue": {
+ "type": "object",
+ "description": "A definition of a queue.",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the queue. When an SNS Operation Binding Object references an SQS queue by name, the identifier should be the one in this field."
+ },
+ "fifoQueue": {
+ "type": "boolean",
+ "description": "Is this a FIFO queue?",
+ "default": false
+ },
+ "deduplicationScope": {
+ "type": "string",
+ "enum": [
+ "queue",
+ "messageGroup"
+ ],
+ "description": "Specifies whether message deduplication occurs at the message group or queue level. Valid values are messageGroup and queue (default).",
+ "default": "queue"
+ },
+ "fifoThroughputLimit": {
+ "type": "string",
+ "enum": [
+ "perQueue",
+ "perMessageGroupId"
+ ],
+ "description": "Specifies whether the FIFO queue throughput quota applies to the entire queue or per message group. Valid values are perQueue (default) and perMessageGroupId.",
+ "default": "perQueue"
+ },
+ "deliveryDelay": {
+ "type": "integer",
+ "description": "The number of seconds to delay before a message sent to the queue can be received. used to create a delay queue.",
+ "minimum": 0,
+ "maximum": 900,
+ "default": 0
+ },
+ "visibilityTimeout": {
+ "type": "integer",
+ "description": "The length of time, in seconds, that a consumer locks a message - hiding it from reads - before it is unlocked and can be read again.",
+ "minimum": 0,
+ "maximum": 43200,
+ "default": 30
+ },
+ "receiveMessageWaitTime": {
+ "type": "integer",
+ "description": "Determines if the queue uses short polling or long polling. Set to zero the queue reads available messages and returns immediately. Set to a non-zero integer, long polling waits the specified number of seconds for messages to arrive before returning.",
+ "default": 0
+ },
+ "messageRetentionPeriod": {
+ "type": "integer",
+ "description": "How long to retain a message on the queue in seconds, unless deleted.",
+ "minimum": 60,
+ "maximum": 1209600,
+ "default": 345600
+ },
+ "redrivePolicy": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json#/definitions/redrivePolicy"
+ },
+ "policy": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json#/definitions/policy"
+ },
+ "tags": {
+ "type": "object",
+ "description": "Key-value pairs that represent AWS tags on the queue."
+ }
+ },
+ "required": [
+ "name",
+ "fifoQueue"
+ ]
+ },
+ "redrivePolicy": {
+ "type": "object",
+ "description": "Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "deadLetterQueue": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json#/definitions/identifier"
+ },
+ "maxReceiveCount": {
+ "type": "integer",
+ "description": "The number of times a message is delivered to the source queue before being moved to the dead-letter queue.",
+ "default": 10
+ }
+ },
+ "required": [
+ "deadLetterQueue"
+ ]
+ },
+ "identifier": {
+ "type": "object",
+ "description": "The SQS queue to use as a dead letter queue (DLQ).",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "arn": {
+ "type": "string",
+ "description": "The target is an ARN. For example, for SQS, the identifier may be an ARN, which will be of the form: arn:aws:sqs:{region}:{account-id}:{queueName}"
+ },
+ "name": {
+ "type": "string",
+ "description": "The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this publish Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field sqs binding."
+ }
+ }
+ },
+ "policy": {
+ "type": "object",
+ "description": "The security policy for the SQS Queue",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "statements": {
+ "type": "array",
+ "description": "An array of statement objects, each of which controls a permission for this queue.",
+ "items": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/channel.json#/definitions/statement"
+ }
+ }
+ },
+ "required": [
+ "statements"
+ ]
+ },
+ "statement": {
+ "type": "object",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "effect": {
+ "type": "string",
+ "enum": [
+ "Allow",
+ "Deny"
+ ]
+ },
+ "principal": {
+ "description": "The AWS account or resource ARN that this statement applies to.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "action": {
+ "description": "The SQS permission being allowed or denied e.g. sqs:ReceiveMessage",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ }
+ },
+ "required": [
+ "effect",
+ "principal",
+ "action"
+ ]
+ }
+ },
+ "examples": [
+ {
+ "queue": {
+ "name": "myQueue",
+ "fifoQueue": true,
+ "deduplicationScope": "messageGroup",
+ "fifoThroughputLimit": "perMessageGroupId",
+ "deliveryDelay": 15,
+ "visibilityTimeout": 60,
+ "receiveMessageWaitTime": 0,
+ "messageRetentionPeriod": 86400,
+ "redrivePolicy": {
+ "deadLetterQueue": {
+ "arn": "arn:aws:SQS:eu-west-1:0000000:123456789"
+ },
+ "maxReceiveCount": 15
+ },
+ "policy": {
+ "statements": [
+ {
+ "effect": "Deny",
+ "principal": "arn:aws:iam::123456789012:user/dec.kolakowski",
+ "action": [
+ "sqs:SendMessage",
+ "sqs:ReceiveMessage"
+ ]
+ }
+ ]
+ },
+ "tags": {
+ "owner": "AsyncAPI.NET",
+ "platform": "AsyncAPIOrg"
+ }
+ },
+ "deadLetterQueue": {
+ "name": "myQueue_error",
+ "deliveryDelay": 0,
+ "visibilityTimeout": 0,
+ "receiveMessageWaitTime": 0,
+ "messageRetentionPeriod": 604800
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/ibmmq/0.1.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/ibmmq/0.1.0/channel.json",
+ "title": "IBM MQ channel bindings object",
+ "description": "This object contains information about the channel representation in IBM MQ. Each channel corresponds to a Queue or Topic within IBM MQ.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "destinationType": {
+ "type": "string",
+ "enum": [
+ "topic",
+ "queue"
+ ],
+ "default": "topic",
+ "description": "Defines the type of AsyncAPI channel."
+ },
+ "queue": {
+ "type": "object",
+ "description": "Defines the properties of a queue.",
+ "properties": {
+ "objectName": {
+ "type": "string",
+ "maxLength": 48,
+ "description": "Defines the name of the IBM MQ queue associated with the channel."
+ },
+ "isPartitioned": {
+ "type": "boolean",
+ "default": false,
+ "description": "Defines if the queue is a cluster queue and therefore partitioned. If 'true', a binding option MAY be specified when accessing the queue. More information on binding options can be found on this page in the IBM MQ Knowledge Center."
+ },
+ "exclusive": {
+ "type": "boolean",
+ "default": false,
+ "description": "Specifies if it is recommended to open the queue exclusively."
+ }
+ },
+ "required": [
+ "objectName"
+ ]
+ },
+ "topic": {
+ "type": "object",
+ "description": "Defines the properties of a topic.",
+ "properties": {
+ "string": {
+ "type": "string",
+ "maxLength": 10240,
+ "description": "The value of the IBM MQ topic string to be used."
+ },
+ "objectName": {
+ "type": "string",
+ "maxLength": 48,
+ "description": "The name of the IBM MQ topic object."
+ },
+ "durablePermitted": {
+ "type": "boolean",
+ "default": true,
+ "description": "Defines if the subscription may be durable."
+ },
+ "lastMsgRetained": {
+ "type": "boolean",
+ "default": false,
+ "description": "Defines if the last message published will be made available to new subscriptions."
+ }
+ }
+ },
+ "maxMsgLength": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 104857600,
+ "description": "The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered. More information on the maximum message length can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q097520_.html) in the IBM MQ Knowledge Center."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0"
+ ],
+ "description": "The version of this binding."
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "destinationType": {
+ "const": "topic"
+ }
+ },
+ "not": {
+ "required": [
+ "queue"
+ ]
+ }
+ },
+ {
+ "properties": {
+ "destinationType": {
+ "const": "queue"
+ }
+ },
+ "required": [
+ "queue"
+ ],
+ "not": {
+ "required": [
+ "topic"
+ ]
+ }
+ }
+ ],
+ "examples": [
+ {
+ "destinationType": "topic",
+ "topic": {
+ "objectName": "myTopicName"
+ },
+ "bindingVersion": "0.1.0"
+ },
+ {
+ "destinationType": "queue",
+ "queue": {
+ "objectName": "myQueueName",
+ "exclusive": true
+ },
+ "bindingVersion": "0.1.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/googlepubsub/0.2.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/googlepubsub/0.2.0/channel.json",
+ "title": "Cloud Pub/Sub Channel Schema",
+ "description": "This object contains information about the channel representation for Google Cloud Pub/Sub.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding."
+ },
+ "labels": {
+ "type": "object"
+ },
+ "messageRetentionDuration": {
+ "type": "string"
+ },
+ "messageStoragePolicy": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "allowedPersistenceRegions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "schemaSettings": {
+ "type": "object",
+ "additionalItems": false,
+ "properties": {
+ "encoding": {
+ "type": "string"
+ },
+ "firstRevisionId": {
+ "type": "string"
+ },
+ "lastRevisionId": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "encoding",
+ "name"
+ ]
+ }
+ },
+ "required": [
+ "schemaSettings"
+ ],
+ "examples": [
+ {
+ "labels": {
+ "label1": "value1",
+ "label2": "value2"
+ },
+ "messageRetentionDuration": "86400s",
+ "messageStoragePolicy": {
+ "allowedPersistenceRegions": [
+ "us-central1",
+ "us-east1"
+ ]
+ },
+ "schemaSettings": {
+ "encoding": "json",
+ "name": "projects/your-project-id/schemas/your-schema"
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/pulsar/0.1.0/channel.json": {
+ "$id": "http://asyncapi.com/bindings/pulsar/0.1.0/channel.json",
+ "title": "Channel Schema",
+ "description": "This object contains information about the channel representation in Pulsar, which covers namespace and topic level admin configuration. This object contains additional information not possible to represent within the core AsyncAPI specification.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "required": [
+ "namespace",
+ "persistence"
+ ],
+ "properties": {
+ "namespace": {
+ "type": "string",
+ "description": "The namespace, the channel is associated with."
+ },
+ "persistence": {
+ "type": "string",
+ "enum": [
+ "persistent",
+ "non-persistent"
+ ],
+ "description": "persistence of the topic in Pulsar."
+ },
+ "compaction": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "Topic compaction threshold given in MB"
+ },
+ "geo-replication": {
+ "type": "array",
+ "description": "A list of clusters the topic is replicated to.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "retention": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "time": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "Time given in Minutes. `0` = Disable message retention."
+ },
+ "size": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "Size given in MegaBytes. `0` = Disable message retention."
+ }
+ }
+ },
+ "ttl": {
+ "type": "integer",
+ "description": "TTL in seconds for the specified topic"
+ },
+ "deduplication": {
+ "type": "boolean",
+ "description": "Whether deduplication of events is enabled or not."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "namespace": "ns1",
+ "persistence": "persistent",
+ "compaction": 1000,
+ "retention": {
+ "time": 15,
+ "size": 1000
+ },
+ "ttl": 360,
+ "geo-replication": [
+ "us-west",
+ "us-east"
+ ],
+ "deduplication": true,
+ "bindingVersion": "0.1.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/operations.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/operations.json",
+ "type": "object",
+ "description": "Holds a dictionary with all the operations this application MUST implement.",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operation.json"
+ }
+ ]
+ },
+ "examples": [
+ {
+ "onUserSignUp": {
+ "title": "User sign up",
+ "summary": "Action to sign a user up.",
+ "description": "A longer description",
+ "channel": {
+ "$ref": "#/channels/userSignup"
+ },
+ "action": "send",
+ "tags": [
+ {
+ "name": "user"
+ },
+ {
+ "name": "signup"
+ },
+ {
+ "name": "register"
+ }
+ ],
+ "bindings": {
+ "amqp": {
+ "ack": false
+ }
+ },
+ "traits": [
+ {
+ "$ref": "#/components/operationTraits/kafka"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/operation.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/operation.json",
+ "type": "object",
+ "description": "Describes a specific operation.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "required": [
+ "action",
+ "channel"
+ ],
+ "properties": {
+ "action": {
+ "type": "string",
+ "description": "Allowed values are send and receive. Use send when it's expected that the application will send a message to the given channel, and receive when the application should expect receiving messages from the given channel.",
+ "enum": [
+ "send",
+ "receive"
+ ]
+ },
+ "channel": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ "messages": {
+ "type": "array",
+ "description": "A list of $ref pointers pointing to the supported Message Objects that can be processed by this operation. It MUST contain a subset of the messages defined in the channel referenced in this operation. Every message processed by this operation MUST be valid against one, and only one, of the message objects referenced in this list. Please note the messages property value MUST be a list of Reference Objects and, therefore, MUST NOT contain Message Objects. However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.",
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ },
+ "reply": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationReply.json"
+ }
+ ]
+ },
+ "traits": {
+ "type": "array",
+ "description": "A list of traits to apply to the operation object. Traits MUST be merged using traits merge mechanism. The resulting object MUST be a valid Operation Object.",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationTrait.json"
+ }
+ ]
+ }
+ },
+ "title": {
+ "type": "string",
+ "description": "A human-friendly title for the operation."
+ },
+ "summary": {
+ "type": "string",
+ "description": "A brief summary of the operation."
+ },
+ "description": {
+ "type": "string",
+ "description": "A longer description of the operation. CommonMark is allowed."
+ },
+ "security": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/securityRequirements.json"
+ },
+ "tags": {
+ "type": "array",
+ "description": "A list of tags for logical grouping and categorization of operations.",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/tag.json"
+ }
+ ]
+ },
+ "uniqueItems": true
+ },
+ "externalDocs": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ },
+ "bindings": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationBindingsObject.json"
+ }
+ ]
+ }
+ },
+ "examples": [
+ {
+ "title": "User sign up",
+ "summary": "Action to sign a user up.",
+ "description": "A longer description",
+ "channel": {
+ "$ref": "#/channels/userSignup"
+ },
+ "action": "send",
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ],
+ "tags": [
+ {
+ "name": "user"
+ },
+ {
+ "name": "signup"
+ },
+ {
+ "name": "register"
+ }
+ ],
+ "bindings": {
+ "amqp": {
+ "ack": false
+ }
+ },
+ "traits": [
+ {
+ "$ref": "#/components/operationTraits/kafka"
+ }
+ ],
+ "messages": [
+ {
+ "$ref": "/components/messages/userSignedUp"
+ }
+ ],
+ "reply": {
+ "address": {
+ "location": "$message.header#/replyTo"
+ },
+ "channel": {
+ "$ref": "#/channels/userSignupReply"
+ },
+ "messages": [
+ {
+ "$ref": "/components/messages/userSignedUpReply"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/operationReply.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/operationReply.json",
+ "type": "object",
+ "description": "Describes the reply part that MAY be applied to an Operation Object. If an operation implements the request/reply pattern, the reply object represents the response message.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "address": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationReplyAddress.json"
+ }
+ ]
+ },
+ "channel": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ "messages": {
+ "type": "array",
+ "description": "A list of $ref pointers pointing to the supported Message Objects that can be processed by this operation as reply. It MUST contain a subset of the messages defined in the channel referenced in this operation reply. Every message processed by this operation MUST be valid against one, and only one, of the message objects referenced in this list. Please note the messages property value MUST be a list of Reference Objects and, therefore, MUST NOT contain Message Objects. However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.",
+ "items": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ }
+ }
+ },
+ "http://asyncapi.com/definitions/3.0.0/operationReplyAddress.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/operationReplyAddress.json",
+ "type": "object",
+ "description": "An object that specifies where an operation has to send the reply",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "required": [
+ "location"
+ ],
+ "properties": {
+ "location": {
+ "type": "string",
+ "description": "A runtime expression that specifies the location of the reply address.",
+ "pattern": "^\\$message\\.(header|payload)#(\\/(([^\\/~])|(~[01]))*)*"
+ },
+ "description": {
+ "type": "string",
+ "description": "An optional description of the address. CommonMark is allowed."
+ }
+ },
+ "examples": [
+ {
+ "description": "Consumer inbox",
+ "location": "$message.header#/replyTo"
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/operationTrait.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/operationTrait.json",
+ "type": "object",
+ "description": "Describes a trait that MAY be applied to an Operation Object. This object MAY contain any property from the Operation Object, except the action, channel and traits ones.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "title": {
+ "description": "A human-friendly title for the operation.",
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operation.json#/properties/title"
+ },
+ "summary": {
+ "description": "A short summary of what the operation is about.",
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operation.json#/properties/summary"
+ },
+ "description": {
+ "description": "A verbose explanation of the operation. CommonMark syntax can be used for rich text representation.",
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operation.json#/properties/description"
+ },
+ "security": {
+ "description": "A declaration of which security schemes are associated with this operation. Only one of the security scheme objects MUST be satisfied to authorize an operation. In cases where Server Security also applies, it MUST also be satisfied.",
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operation.json#/properties/security"
+ },
+ "tags": {
+ "description": "A list of tags for logical grouping and categorization of operations.",
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operation.json#/properties/tags"
+ },
+ "externalDocs": {
+ "description": "Additional external documentation for this operation.",
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operation.json#/properties/externalDocs"
+ },
+ "bindings": {
+ "description": "A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation.",
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationBindingsObject.json"
+ }
+ ]
+ }
+ },
+ "examples": [
+ {
+ "bindings": {
+ "amqp": {
+ "ack": false
+ }
+ }
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/operationBindingsObject.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/operationBindingsObject.json",
+ "type": "object",
+ "description": "Map describing protocol-specific definitions for an operation.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "http": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0",
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/http/0.3.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/http/0.2.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/http/0.3.0/operation.json"
+ }
+ }
+ ]
+ },
+ "ws": {},
+ "amqp": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/amqp/0.3.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/amqp/0.3.0/operation.json"
+ }
+ }
+ ]
+ },
+ "amqp1": {},
+ "mqtt": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/mqtt/0.2.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/mqtt/0.2.0/operation.json"
+ }
+ }
+ ]
+ },
+ "kafka": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.5.0",
+ "0.4.0",
+ "0.3.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.5.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.5.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.5.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.4.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.4.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/kafka/0.3.0/operation.json"
+ }
+ }
+ ]
+ },
+ "anypointmq": {},
+ "nats": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/nats/0.1.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/nats/0.1.0/operation.json"
+ }
+ }
+ ]
+ },
+ "jms": {},
+ "sns": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.1.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.1.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json"
+ }
+ }
+ ]
+ },
+ "sqs": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/operation.json"
+ }
+ }
+ ]
+ },
+ "stomp": {},
+ "redis": {},
+ "ibmmq": {},
+ "solace": {
+ "properties": {
+ "bindingVersion": {
+ "enum": [
+ "0.4.0",
+ "0.3.0",
+ "0.2.0"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "description": "If no bindingVersion specified, use the latest binding",
+ "if": {
+ "not": {
+ "required": [
+ "bindingVersion"
+ ]
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/solace/0.4.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.4.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/solace/0.4.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.3.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/solace/0.3.0/operation.json"
+ }
+ },
+ {
+ "if": {
+ "required": [
+ "bindingVersion"
+ ],
+ "properties": {
+ "bindingVersion": {
+ "const": "0.2.0"
+ }
+ }
+ },
+ "then": {
+ "$ref": "http://asyncapi.com/bindings/solace/0.2.0/operation.json"
+ }
+ }
+ ]
+ },
+ "googlepubsub": {}
+ }
+ },
+ "http://asyncapi.com/bindings/http/0.3.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/http/0.3.0/operation.json",
+ "title": "HTTP operation bindings object",
+ "description": "This object contains information about the operation representation in HTTP.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "GET",
+ "PUT",
+ "POST",
+ "PATCH",
+ "DELETE",
+ "HEAD",
+ "OPTIONS",
+ "CONNECT",
+ "TRACE"
+ ],
+ "description": "When 'type' is 'request', this is the HTTP method, otherwise it MUST be ignored. Its value MUST be one of 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', and 'TRACE'."
+ },
+ "query": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "A Schema object containing the definitions for each query parameter. This schema MUST be of type 'object' and have a properties key."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "query": {
+ "type": "object",
+ "required": [
+ "companyId"
+ ],
+ "properties": {
+ "companyId": {
+ "type": "number",
+ "minimum": 1,
+ "description": "The Id of the company."
+ }
+ },
+ "additionalProperties": false
+ },
+ "bindingVersion": "0.3.0"
+ },
+ {
+ "method": "GET",
+ "query": {
+ "type": "object",
+ "required": [
+ "companyId"
+ ],
+ "properties": {
+ "companyId": {
+ "type": "number",
+ "minimum": 1,
+ "description": "The Id of the company."
+ }
+ },
+ "additionalProperties": false
+ },
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/http/0.2.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/http/0.2.0/operation.json",
+ "title": "HTTP operation bindings object",
+ "description": "This object contains information about the operation representation in HTTP.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "GET",
+ "PUT",
+ "POST",
+ "PATCH",
+ "DELETE",
+ "HEAD",
+ "OPTIONS",
+ "CONNECT",
+ "TRACE"
+ ],
+ "description": "When 'type' is 'request', this is the HTTP method, otherwise it MUST be ignored. Its value MUST be one of 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', and 'TRACE'."
+ },
+ "query": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "A Schema object containing the definitions for each query parameter. This schema MUST be of type 'object' and have a properties key."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "query": {
+ "type": "object",
+ "required": [
+ "companyId"
+ ],
+ "properties": {
+ "companyId": {
+ "type": "number",
+ "minimum": 1,
+ "description": "The Id of the company."
+ }
+ },
+ "additionalProperties": false
+ },
+ "bindingVersion": "0.2.0"
+ },
+ {
+ "method": "GET",
+ "query": {
+ "type": "object",
+ "required": [
+ "companyId"
+ ],
+ "properties": {
+ "companyId": {
+ "type": "number",
+ "minimum": 1,
+ "description": "The Id of the company."
+ }
+ },
+ "additionalProperties": false
+ },
+ "bindingVersion": "0.2.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/amqp/0.3.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/amqp/0.3.0/operation.json",
+ "title": "AMQP operation bindings object",
+ "description": "This object contains information about the operation representation in AMQP.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "expiration": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "TTL (Time-To-Live) for the message. It MUST be greater than or equal to zero."
+ },
+ "userId": {
+ "type": "string",
+ "description": "Identifies the user who has sent the message."
+ },
+ "cc": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The routing keys the message should be routed to at the time of publishing."
+ },
+ "priority": {
+ "type": "integer",
+ "description": "A priority for the message."
+ },
+ "deliveryMode": {
+ "type": "integer",
+ "enum": [
+ 1,
+ 2
+ ],
+ "description": "Delivery mode of the message. Its value MUST be either 1 (transient) or 2 (persistent)."
+ },
+ "mandatory": {
+ "type": "boolean",
+ "description": "Whether the message is mandatory or not."
+ },
+ "bcc": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Like cc but consumers will not receive this information."
+ },
+ "timestamp": {
+ "type": "boolean",
+ "description": "Whether the message should include a timestamp or not."
+ },
+ "ack": {
+ "type": "boolean",
+ "description": "Whether the consumer should ack the message or not."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, \"latest\" MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "expiration": 100000,
+ "userId": "guest",
+ "cc": [
+ "user.logs"
+ ],
+ "priority": 10,
+ "deliveryMode": 2,
+ "mandatory": false,
+ "bcc": [
+ "external.audit"
+ ],
+ "timestamp": true,
+ "ack": false,
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/mqtt/0.2.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/mqtt/0.2.0/operation.json",
+ "title": "MQTT operation bindings object",
+ "description": "This object contains information about the operation representation in MQTT.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "qos": {
+ "type": "integer",
+ "enum": [
+ 0,
+ 1,
+ 2
+ ],
+ "description": "Defines the Quality of Service (QoS) levels for the message flow between client and server. Its value MUST be either 0 (At most once delivery), 1 (At least once delivery), or 2 (Exactly once delivery)."
+ },
+ "retain": {
+ "type": "boolean",
+ "description": "Whether the broker should retain the message or not."
+ },
+ "messageExpiryInterval": {
+ "oneOf": [
+ {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 4294967295
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ }
+ ],
+ "description": "Lifetime of the message in seconds"
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "qos": 2,
+ "retain": true,
+ "messageExpiryInterval": 60,
+ "bindingVersion": "0.2.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.5.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.5.0/operation.json",
+ "title": "Operation Schema",
+ "description": "This object contains information about the operation representation in Kafka.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "groupId": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "Id of the consumer group."
+ },
+ "clientId": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "Id of the consumer inside a consumer group."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.5.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "groupId": {
+ "type": "string",
+ "enum": [
+ "myGroupId"
+ ]
+ },
+ "clientId": {
+ "type": "string",
+ "enum": [
+ "myClientId"
+ ]
+ },
+ "bindingVersion": "0.5.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.4.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.4.0/operation.json",
+ "title": "Operation Schema",
+ "description": "This object contains information about the operation representation in Kafka.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "groupId": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "Id of the consumer group."
+ },
+ "clientId": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "Id of the consumer inside a consumer group."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.4.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "groupId": {
+ "type": "string",
+ "enum": [
+ "myGroupId"
+ ]
+ },
+ "clientId": {
+ "type": "string",
+ "enum": [
+ "myClientId"
+ ]
+ },
+ "bindingVersion": "0.4.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/kafka/0.3.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/kafka/0.3.0/operation.json",
+ "title": "Operation Schema",
+ "description": "This object contains information about the operation representation in Kafka.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "groupId": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "Id of the consumer group."
+ },
+ "clientId": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/schema.json",
+ "description": "Id of the consumer inside a consumer group."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "groupId": {
+ "type": "string",
+ "enum": [
+ "myGroupId"
+ ]
+ },
+ "clientId": {
+ "type": "string",
+ "enum": [
+ "myClientId"
+ ]
+ },
+ "bindingVersion": "0.3.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/nats/0.1.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/nats/0.1.0/operation.json",
+ "title": "NATS operation bindings object",
+ "description": "This object contains information about the operation representation in NATS.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "queue": {
+ "type": "string",
+ "description": "Defines the name of the queue to use. It MUST NOT exceed 255 characters.",
+ "maxLength": 255
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "queue": "MyCustomQueue",
+ "bindingVersion": "0.1.0"
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/sns/0.1.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/sns/0.1.0/operation.json",
+ "title": "Operation Schema",
+ "description": "This object contains information about the operation representation in SNS.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "topic": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json#/definitions/identifier",
+ "description": "Often we can assume that the SNS Topic is the channel name-we provide this field in case the you need to supply the ARN, or the Topic name is not the channel name in the AsyncAPI document."
+ },
+ "consumers": {
+ "type": "array",
+ "description": "The protocols that listen to this topic and their endpoints.",
+ "items": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json#/definitions/consumer"
+ },
+ "minItems": 1
+ },
+ "deliveryPolicy": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json#/definitions/deliveryPolicy",
+ "description": "Policy for retries to HTTP. The field is the default for HTTP receivers of the SNS Topic which may be overridden by a specific consumer."
+ },
+ "bindingVersion": {
+ "type": "string",
+ "description": "The version of this binding.",
+ "default": "latest"
+ }
+ },
+ "required": [
+ "consumers"
+ ],
+ "definitions": {
+ "identifier": {
+ "type": "object",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "url": {
+ "type": "string",
+ "description": "The endpoint is a URL."
+ },
+ "email": {
+ "type": "string",
+ "description": "The endpoint is an email address."
+ },
+ "phone": {
+ "type": "string",
+ "description": "The endpoint is a phone number."
+ },
+ "arn": {
+ "type": "string",
+ "description": "The target is an ARN. For example, for SQS, the identifier may be an ARN, which will be of the form: arn:aws:sqs:{region}:{account-id}:{queueName}"
+ },
+ "name": {
+ "type": "string",
+ "description": "The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this publish Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field sqs binding. We don't use $ref because we are referring, not including."
+ }
+ }
+ },
+ "consumer": {
+ "type": "object",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "protocol": {
+ "description": "The protocol that this endpoint receives messages by.",
+ "type": "string",
+ "enum": [
+ "http",
+ "https",
+ "email",
+ "email-json",
+ "sms",
+ "sqs",
+ "application",
+ "lambda",
+ "firehose"
+ ]
+ },
+ "endpoint": {
+ "description": "The endpoint messages are delivered to.",
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json#/definitions/identifier"
+ },
+ "filterPolicy": {
+ "type": "object",
+ "description": "Only receive a subset of messages from the channel, determined by this policy. Depending on the FilterPolicyScope, a map of either a message attribute or message body to an array of possible matches. The match may be a simple string for an exact match, but it may also be an object that represents a constraint and values for that constraint.",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ {
+ "type": "string"
+ },
+ {
+ "type": "object"
+ }
+ ]
+ }
+ },
+ "filterPolicyScope": {
+ "type": "string",
+ "description": "Determines whether the FilterPolicy applies to MessageAttributes or MessageBody.",
+ "enum": [
+ "MessageAttributes",
+ "MessageBody"
+ ],
+ "default": "MessageAttributes"
+ },
+ "rawMessageDelivery": {
+ "type": "boolean",
+ "description": "If true AWS SNS attributes are removed from the body, and for SQS, SNS message attributes are copied to SQS message attributes. If false the SNS attributes are included in the body."
+ },
+ "redrivePolicy": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json#/definitions/redrivePolicy"
+ },
+ "deliveryPolicy": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json#/definitions/deliveryPolicy",
+ "description": "Policy for retries to HTTP. The parameter is for that SNS Subscription and overrides any policy on the SNS Topic."
+ },
+ "displayName": {
+ "type": "string",
+ "description": "The display name to use with an SNS subscription"
+ }
+ },
+ "required": [
+ "protocol",
+ "endpoint",
+ "rawMessageDelivery"
+ ]
+ },
+ "deliveryPolicy": {
+ "type": "object",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "minDelayTarget": {
+ "type": "integer",
+ "description": "The minimum delay for a retry in seconds."
+ },
+ "maxDelayTarget": {
+ "type": "integer",
+ "description": "The maximum delay for a retry in seconds."
+ },
+ "numRetries": {
+ "type": "integer",
+ "description": "The total number of retries, including immediate, pre-backoff, backoff, and post-backoff retries."
+ },
+ "numNoDelayRetries": {
+ "type": "integer",
+ "description": "The number of immediate retries (with no delay)."
+ },
+ "numMinDelayRetries": {
+ "type": "integer",
+ "description": "The number of immediate retries (with delay)."
+ },
+ "numMaxDelayRetries": {
+ "type": "integer",
+ "description": "The number of post-backoff phase retries, with the maximum delay between retries."
+ },
+ "backoffFunction": {
+ "type": "string",
+ "description": "The algorithm for backoff between retries.",
+ "enum": [
+ "arithmetic",
+ "exponential",
+ "geometric",
+ "linear"
+ ]
+ },
+ "maxReceivesPerSecond": {
+ "type": "integer",
+ "description": "The maximum number of deliveries per second, per subscription."
+ }
+ }
+ },
+ "redrivePolicy": {
+ "type": "object",
+ "description": "Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "deadLetterQueue": {
+ "$ref": "http://asyncapi.com/bindings/sns/0.1.0/operation.json#/definitions/identifier",
+ "description": "The SQS queue to use as a dead letter queue (DLQ)."
+ },
+ "maxReceiveCount": {
+ "type": "integer",
+ "description": "The number of times a message is delivered to the source queue before being moved to the dead-letter queue.",
+ "default": 10
+ }
+ },
+ "required": [
+ "deadLetterQueue"
+ ]
+ }
+ },
+ "examples": [
+ {
+ "topic": {
+ "name": "someTopic"
+ },
+ "consumers": [
+ {
+ "protocol": "sqs",
+ "endpoint": {
+ "name": "someQueue"
+ },
+ "filterPolicy": {
+ "store": [
+ "asyncapi_corp"
+ ],
+ "event": [
+ {
+ "anything-but": "order_cancelled"
+ }
+ ],
+ "customer_interests": [
+ "rugby",
+ "football",
+ "baseball"
+ ]
+ },
+ "filterPolicyScope": "MessageAttributes",
+ "rawMessageDelivery": false,
+ "redrivePolicy": {
+ "deadLetterQueue": {
+ "arn": "arn:aws:SQS:eu-west-1:0000000:123456789"
+ },
+ "maxReceiveCount": 25
+ },
+ "deliveryPolicy": {
+ "minDelayTarget": 10,
+ "maxDelayTarget": 100,
+ "numRetries": 5,
+ "numNoDelayRetries": 2,
+ "numMinDelayRetries": 3,
+ "numMaxDelayRetries": 5,
+ "backoffFunction": "linear",
+ "maxReceivesPerSecond": 2
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/sqs/0.2.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/sqs/0.2.0/operation.json",
+ "title": "Operation Schema",
+ "description": "This object contains information about the operation representation in SQS.",
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "queues": {
+ "type": "array",
+ "description": "Queue objects that are either the endpoint for an SNS Operation Binding Object, or the deadLetterQueue of the SQS Operation Binding Object.",
+ "items": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/operation.json#/definitions/queue"
+ }
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.1.0",
+ "0.2.0"
+ ],
+ "description": "The version of this binding. If omitted, 'latest' MUST be assumed.",
+ "default": "latest"
+ }
+ },
+ "required": [
+ "queues"
+ ],
+ "definitions": {
+ "queue": {
+ "type": "object",
+ "description": "A definition of a queue.",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "$ref": {
+ "type": "string",
+ "description": "Allows for an external definition of a queue. The referenced structure MUST be in the format of a Queue. If there are conflicts between the referenced definition and this Queue's definition, the behavior is undefined."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the queue. When an SNS Operation Binding Object references an SQS queue by name, the identifier should be the one in this field."
+ },
+ "fifoQueue": {
+ "type": "boolean",
+ "description": "Is this a FIFO queue?",
+ "default": false
+ },
+ "deduplicationScope": {
+ "type": "string",
+ "enum": [
+ "queue",
+ "messageGroup"
+ ],
+ "description": "Specifies whether message deduplication occurs at the message group or queue level. Valid values are messageGroup and queue (default).",
+ "default": "queue"
+ },
+ "fifoThroughputLimit": {
+ "type": "string",
+ "enum": [
+ "perQueue",
+ "perMessageGroupId"
+ ],
+ "description": "Specifies whether the FIFO queue throughput quota applies to the entire queue or per message group. Valid values are perQueue (default) and perMessageGroupId.",
+ "default": "perQueue"
+ },
+ "deliveryDelay": {
+ "type": "integer",
+ "description": "The number of seconds to delay before a message sent to the queue can be received. Used to create a delay queue.",
+ "minimum": 0,
+ "maximum": 900,
+ "default": 0
+ },
+ "visibilityTimeout": {
+ "type": "integer",
+ "description": "The length of time, in seconds, that a consumer locks a message - hiding it from reads - before it is unlocked and can be read again.",
+ "minimum": 0,
+ "maximum": 43200,
+ "default": 30
+ },
+ "receiveMessageWaitTime": {
+ "type": "integer",
+ "description": "Determines if the queue uses short polling or long polling. Set to zero the queue reads available messages and returns immediately. Set to a non-zero integer, long polling waits the specified number of seconds for messages to arrive before returning.",
+ "default": 0
+ },
+ "messageRetentionPeriod": {
+ "type": "integer",
+ "description": "How long to retain a message on the queue in seconds, unless deleted.",
+ "minimum": 60,
+ "maximum": 1209600,
+ "default": 345600
+ },
+ "redrivePolicy": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/operation.json#/definitions/redrivePolicy"
+ },
+ "policy": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/operation.json#/definitions/policy"
+ },
+ "tags": {
+ "type": "object",
+ "description": "Key-value pairs that represent AWS tags on the queue."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "redrivePolicy": {
+ "type": "object",
+ "description": "Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "deadLetterQueue": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/operation.json#/definitions/identifier"
+ },
+ "maxReceiveCount": {
+ "type": "integer",
+ "description": "The number of times a message is delivered to the source queue before being moved to the dead-letter queue.",
+ "default": 10
+ }
+ },
+ "required": [
+ "deadLetterQueue"
+ ]
+ },
+ "identifier": {
+ "type": "object",
+ "description": "The SQS queue to use as a dead letter queue (DLQ).",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "arn": {
+ "type": "string",
+ "description": "The target is an ARN. For example, for SQS, the identifier may be an ARN, which will be of the form: arn:aws:sqs:{region}:{account-id}:{queueName}"
+ },
+ "name": {
+ "type": "string",
+ "description": "The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this publish Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field sqs binding."
+ }
+ }
+ },
+ "policy": {
+ "type": "object",
+ "description": "The security policy for the SQS Queue",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "statements": {
+ "type": "array",
+ "description": "An array of statement objects, each of which controls a permission for this queue.",
+ "items": {
+ "$ref": "http://asyncapi.com/bindings/sqs/0.2.0/operation.json#/definitions/statement"
+ }
+ }
+ },
+ "required": [
+ "statements"
+ ]
+ },
+ "statement": {
+ "type": "object",
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "effect": {
+ "type": "string",
+ "enum": [
+ "Allow",
+ "Deny"
+ ]
+ },
+ "principal": {
+ "description": "The AWS account or resource ARN that this statement applies to.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "action": {
+ "description": "The SQS permission being allowed or denied e.g. sqs:ReceiveMessage",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ }
+ },
+ "required": [
+ "effect",
+ "principal",
+ "action"
+ ]
+ }
+ },
+ "examples": [
+ {
+ "queues": [
+ {
+ "name": "myQueue",
+ "fifoQueue": true,
+ "deduplicationScope": "messageGroup",
+ "fifoThroughputLimit": "perMessageGroupId",
+ "deliveryDelay": 10,
+ "redrivePolicy": {
+ "deadLetterQueue": {
+ "name": "myQueue_error"
+ },
+ "maxReceiveCount": 15
+ },
+ "policy": {
+ "statements": [
+ {
+ "effect": "Deny",
+ "principal": "arn:aws:iam::123456789012:user/dec.kolakowski",
+ "action": [
+ "sqs:SendMessage",
+ "sqs:ReceiveMessage"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "myQueue_error",
+ "deliveryDelay": 10
+ }
+ ]
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/solace/0.4.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/solace/0.4.0/operation.json",
+ "title": "Solace operation bindings object",
+ "description": "This object contains information about the operation representation in Solace.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.4.0"
+ ],
+ "description": "The version of this binding. If omitted, \"latest\" MUST be assumed."
+ },
+ "destinations": {
+ "description": "The list of Solace destinations referenced in the operation.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "deliveryMode": {
+ "type": "string",
+ "enum": [
+ "direct",
+ "persistent"
+ ]
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "destinationType": {
+ "type": "string",
+ "const": "queue",
+ "description": "If the type is queue, then the subscriber can bind to the queue. The queue subscribes to the given topicSubscriptions. If no topicSubscriptions are provied, the queue will subscribe to the topic as represented by the channel name."
+ },
+ "queue": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the queue"
+ },
+ "topicSubscriptions": {
+ "type": "array",
+ "description": "The list of topics that the queue subscribes to.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "accessType": {
+ "type": "string",
+ "enum": [
+ "exclusive",
+ "nonexclusive"
+ ]
+ },
+ "maxTtl": {
+ "type": "string",
+ "description": "The maximum TTL to apply to messages to be spooled."
+ },
+ "maxMsgSpoolUsage": {
+ "type": "string",
+ "description": "The maximum amount of message spool that the given queue may use"
+ }
+ }
+ }
+ }
+ },
+ {
+ "properties": {
+ "destinationType": {
+ "type": "string",
+ "const": "topic",
+ "description": "If the type is topic, then the subscriber subscribes to the given topicSubscriptions. If no topicSubscriptions are provided, the client will subscribe to the topic as represented by the channel name."
+ },
+ "topicSubscriptions": {
+ "type": "array",
+ "description": "The list of topics that the client subscribes to.",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "timeToLive": {
+ "type": "integer",
+ "description": "Interval in milliseconds or a Schema Object containing the definition of the lifetime of the message."
+ },
+ "priority": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 255,
+ "description": "The valid priority value range is 0-255 with 0 as the lowest priority and 255 as the highest or a Schema Object containing the definition of the priority."
+ },
+ "dmqEligible": {
+ "type": "boolean",
+ "description": "Set the message to be eligible to be moved to a Dead Message Queue. The default value is false."
+ }
+ },
+ "examples": [
+ {
+ "bindingVersion": "0.4.0",
+ "destinations": [
+ {
+ "destinationType": "queue",
+ "queue": {
+ "name": "sampleQueue",
+ "topicSubscriptions": [
+ "samples/*"
+ ],
+ "accessType": "nonexclusive"
+ }
+ },
+ {
+ "destinationType": "topic",
+ "topicSubscriptions": [
+ "samples/*"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/solace/0.3.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/solace/0.3.0/operation.json",
+ "title": "Solace operation bindings object",
+ "description": "This object contains information about the operation representation in Solace.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "destinations": {
+ "description": "The list of Solace destinations referenced in the operation.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "deliveryMode": {
+ "type": "string",
+ "enum": [
+ "direct",
+ "persistent"
+ ]
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "destinationType": {
+ "type": "string",
+ "const": "queue",
+ "description": "If the type is queue, then the subscriber can bind to the queue. The queue subscribes to the given topicSubscriptions. If no topicSubscriptions are provied, the queue will subscribe to the topic as represented by the channel name."
+ },
+ "queue": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the queue"
+ },
+ "topicSubscriptions": {
+ "type": "array",
+ "description": "The list of topics that the queue subscribes to.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "accessType": {
+ "type": "string",
+ "enum": [
+ "exclusive",
+ "nonexclusive"
+ ]
+ },
+ "maxTtl": {
+ "type": "string",
+ "description": "The maximum TTL to apply to messages to be spooled."
+ },
+ "maxMsgSpoolUsage": {
+ "type": "string",
+ "description": "The maximum amount of message spool that the given queue may use"
+ }
+ }
+ }
+ }
+ },
+ {
+ "properties": {
+ "destinationType": {
+ "type": "string",
+ "const": "topic",
+ "description": "If the type is topic, then the subscriber subscribes to the given topicSubscriptions. If no topicSubscriptions are provided, the client will subscribe to the topic as represented by the channel name."
+ },
+ "topicSubscriptions": {
+ "type": "array",
+ "description": "The list of topics that the client subscribes to.",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.3.0"
+ ],
+ "description": "The version of this binding. If omitted, \"latest\" MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "bindingVersion": "0.3.0",
+ "destinations": [
+ {
+ "destinationType": "queue",
+ "queue": {
+ "name": "sampleQueue",
+ "topicSubscriptions": [
+ "samples/*"
+ ],
+ "accessType": "nonexclusive"
+ }
+ },
+ {
+ "destinationType": "topic",
+ "topicSubscriptions": [
+ "samples/*"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "http://asyncapi.com/bindings/solace/0.2.0/operation.json": {
+ "$id": "http://asyncapi.com/bindings/solace/0.2.0/operation.json",
+ "title": "Solace operation bindings object",
+ "description": "This object contains information about the operation representation in Solace.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "destinations": {
+ "description": "The list of Solace destinations referenced in the operation.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "deliveryMode": {
+ "type": "string",
+ "enum": [
+ "direct",
+ "persistent"
+ ]
+ }
+ },
+ "oneOf": [
+ {
+ "properties": {
+ "destinationType": {
+ "type": "string",
+ "const": "queue",
+ "description": "If the type is queue, then the subscriber can bind to the queue. The queue subscribes to the given topicSubscriptions. If no topicSubscriptions are provied, the queue will subscribe to the topic as represented by the channel name."
+ },
+ "queue": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the queue"
+ },
+ "topicSubscriptions": {
+ "type": "array",
+ "description": "The list of topics that the queue subscribes to.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "accessType": {
+ "type": "string",
+ "enum": [
+ "exclusive",
+ "nonexclusive"
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "properties": {
+ "destinationType": {
+ "type": "string",
+ "const": "topic",
+ "description": "If the type is topic, then the subscriber subscribes to the given topicSubscriptions. If no topicSubscriptions are provided, the client will subscribe to the topic as represented by the channel name."
+ },
+ "topicSubscriptions": {
+ "type": "array",
+ "description": "The list of topics that the client subscribes to.",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "bindingVersion": {
+ "type": "string",
+ "enum": [
+ "0.2.0"
+ ],
+ "description": "The version of this binding. If omitted, \"latest\" MUST be assumed."
+ }
+ },
+ "examples": [
+ {
+ "bindingVersion": "0.2.0",
+ "destinations": [
+ {
+ "destinationType": "queue",
+ "queue": {
+ "name": "sampleQueue",
+ "topicSubscriptions": [
+ "samples/*"
+ ],
+ "accessType": "nonexclusive"
+ }
+ },
+ {
+ "destinationType": "topic",
+ "topicSubscriptions": [
+ "samples/*"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "http://asyncapi.com/definitions/3.0.0/components.json": {
+ "$id": "http://asyncapi.com/definitions/3.0.0/components.json",
+ "type": "object",
+ "description": "An object to hold a set of reusable objects for different aspects of the AsyncAPI specification. All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object.",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^x-[\\w\\d\\.\\x2d_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/specificationExtension.json"
+ }
+ },
+ "properties": {
+ "schemas": {
+ "type": "object",
+ "description": "An object to hold reusable Schema Object. If this is a Schema Object, then the schemaFormat will be assumed to be 'application/vnd.aai.asyncapi+json;version=asyncapi' where the version is equal to the AsyncAPI Version String.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/anySchema.json"
+ }
+ }
+ },
+ "servers": {
+ "type": "object",
+ "description": "An object to hold reusable Server Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/server.json"
+ }
+ ]
+ }
+ }
+ },
+ "channels": {
+ "type": "object",
+ "description": "An object to hold reusable Channel Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/channel.json"
+ }
+ ]
+ }
+ }
+ },
+ "serverVariables": {
+ "type": "object",
+ "description": "An object to hold reusable Server Variable Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/serverVariable.json"
+ }
+ ]
+ }
+ }
+ },
+ "operations": {
+ "type": "object",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operation.json"
+ }
+ ]
+ }
+ }
+ },
+ "messages": {
+ "type": "object",
+ "description": "An object to hold reusable Message Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageObject.json"
+ }
+ ]
+ }
+ }
+ },
+ "securitySchemes": {
+ "type": "object",
+ "description": "An object to hold reusable Security Scheme Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/SecurityScheme.json"
+ }
+ ]
+ }
+ }
+ },
+ "parameters": {
+ "type": "object",
+ "description": "An object to hold reusable Parameter Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/parameter.json"
+ }
+ ]
+ }
+ }
+ },
+ "correlationIds": {
+ "type": "object",
+ "description": "An object to hold reusable Correlation ID Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/correlationId.json"
+ }
+ ]
+ }
+ }
+ },
+ "operationTraits": {
+ "type": "object",
+ "description": "An object to hold reusable Operation Trait Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationTrait.json"
+ }
+ ]
+ }
+ }
+ },
+ "messageTraits": {
+ "type": "object",
+ "description": "An object to hold reusable Message Trait Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageTrait.json"
+ }
+ ]
+ }
+ }
+ },
+ "replies": {
+ "type": "object",
+ "description": "An object to hold reusable Operation Reply Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationReply.json"
+ }
+ ]
+ }
+ }
+ },
+ "replyAddresses": {
+ "type": "object",
+ "description": "An object to hold reusable Operation Reply Address Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationReplyAddress.json"
+ }
+ ]
+ }
+ }
+ },
+ "serverBindings": {
+ "type": "object",
+ "description": "An object to hold reusable Server Bindings Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/serverBindingsObject.json"
+ }
+ ]
+ }
+ }
+ },
+ "channelBindings": {
+ "type": "object",
+ "description": "An object to hold reusable Channel Bindings Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/channelBindingsObject.json"
+ }
+ ]
+ }
+ }
+ },
+ "operationBindings": {
+ "type": "object",
+ "description": "An object to hold reusable Operation Bindings Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/operationBindingsObject.json"
+ }
+ ]
+ }
+ }
+ },
+ "messageBindings": {
+ "type": "object",
+ "description": "An object to hold reusable Message Bindings Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/messageBindingsObject.json"
+ }
+ ]
+ }
+ }
+ },
+ "tags": {
+ "type": "object",
+ "description": "An object to hold reusable Tag Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/tag.json"
+ }
+ ]
+ }
+ }
+ },
+ "externalDocs": {
+ "type": "object",
+ "description": "An object to hold reusable External Documentation Objects.",
+ "patternProperties": {
+ "^[\\w\\d\\.\\-_]+$": {
+ "oneOf": [
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/Reference.json"
+ },
+ {
+ "$ref": "http://asyncapi.com/definitions/3.0.0/externalDocs.json"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "examples": [
+ {
+ "components": {
+ "schemas": {
+ "Category": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "name": {
+ "type": "string"
+ }
+ }
+ },
+ "Tag": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "name": {
+ "type": "string"
+ }
+ }
+ },
+ "AvroExample": {
+ "schemaFormat": "application/vnd.apache.avro+json;version=1.9.0",
+ "schema": {
+ "$ref": "path/to/user-create.avsc#/UserCreate"
+ }
+ }
+ },
+ "servers": {
+ "development": {
+ "host": "{stage}.in.mycompany.com:{port}",
+ "description": "RabbitMQ broker",
+ "protocol": "amqp",
+ "protocolVersion": "0-9-1",
+ "variables": {
+ "stage": {
+ "$ref": "#/components/serverVariables/stage"
+ },
+ "port": {
+ "$ref": "#/components/serverVariables/port"
+ }
+ }
+ }
+ },
+ "serverVariables": {
+ "stage": {
+ "default": "demo",
+ "description": "This value is assigned by the service provider, in this example `mycompany.com`"
+ },
+ "port": {
+ "enum": [
+ "5671",
+ "5672"
+ ],
+ "default": "5672"
+ }
+ },
+ "channels": {
+ "user/signedup": {
+ "subscribe": {
+ "message": {
+ "$ref": "#/components/messages/userSignUp"
+ }
+ }
+ }
+ },
+ "messages": {
+ "userSignUp": {
+ "summary": "Action to sign a user up.",
+ "description": "Multiline description of what this action does.\nHere you have another line.\n",
+ "tags": [
+ {
+ "name": "user"
+ },
+ {
+ "name": "signup"
+ }
+ ],
+ "headers": {
+ "type": "object",
+ "properties": {
+ "applicationInstanceId": {
+ "description": "Unique identifier for a given instance of the publishing application",
+ "type": "string"
+ }
+ }
+ },
+ "payload": {
+ "type": "object",
+ "properties": {
+ "user": {
+ "$ref": "#/components/schemas/userCreate"
+ },
+ "signup": {
+ "$ref": "#/components/schemas/signup"
+ }
+ }
+ }
+ }
+ },
+ "parameters": {
+ "userId": {
+ "description": "Id of the user."
+ }
+ },
+ "correlationIds": {
+ "default": {
+ "description": "Default Correlation ID",
+ "location": "$message.header#/correlationId"
+ }
+ },
+ "messageTraits": {
+ "commonHeaders": {
+ "headers": {
+ "type": "object",
+ "properties": {
+ "my-app-header": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "description": "!!Auto generated!! \n Do not manually edit. "
+}
\ No newline at end of file
diff --git a/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml b/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml
index 72a2e0b69..d772f000b 100644
--- a/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml
+++ b/pygeoapi/resources/schemas/config/pygeoapi-config-0.x.yml
@@ -185,10 +185,10 @@ properties:
channel:
type: string
description: channel to subscribe to
- show_link:
+ hidden:
type: boolean
- default: true
- description: whether to display broker link on API responses
+ default: false
+ description: whether to hide broker link on API responses
required:
- url
required:
diff --git a/pygeoapi/starlette_app.py b/pygeoapi/starlette_app.py
index dfe059f8a..ffb5b656f 100644
--- a/pygeoapi/starlette_app.py
+++ b/pygeoapi/starlette_app.py
@@ -5,7 +5,7 @@
# Abdulazeez Abdulazeez Adeshina
#
# Copyright (c) 2025 Francesco Bartoli
-# Copyright (c) 2025 Tom Kralidis
+# Copyright (c) 2026 Tom Kralidis
# Copyright (c) 2022 Abdulazeez Abdulazeez Adeshina
#
# Permission is hereby granted, free of charge, to any person
@@ -59,6 +59,7 @@
import pygeoapi.api.processes as processes_api
import pygeoapi.api.stac as stac_api
import pygeoapi.api.tiles as tiles_api
+from pygeoapi.asyncapi import load_asyncapi_document
from pygeoapi.openapi import load_openapi_document
from pygeoapi.config import get_config
from pygeoapi.util import get_api_rules
@@ -69,6 +70,7 @@
raise RuntimeError('PYGEOAPI_OPENAPI environment variable not set')
OPENAPI = load_openapi_document()
+ASYNCAPI = load_asyncapi_document()
if CONFIG['server'].get('admin'):
import pygeoapi.api.admin as admin_api
@@ -86,7 +88,7 @@
API_RULES = get_api_rules(CONFIG)
-api_ = API(CONFIG, OPENAPI)
+api_ = API(CONFIG, OPENAPI, ASYNCAPI)
def call_api_threadsafe(
@@ -167,6 +169,17 @@ async def openapi(request: Request) -> Response:
return await execute_from_starlette(core_api.openapi_, request)
+async def asyncapi(request: Request) -> Response:
+ """
+ AsyncAPI endpoint
+
+ :param request: Starlette Request instance
+
+ :returns: Starlette HTTP Response
+ """
+ return await execute_from_starlette(core_api.asyncapi_, request)
+
+
async def conformance(request: Request) -> Response:
"""
OGC API conformance endpoint
@@ -699,6 +712,7 @@ async def __call__(self, scope: Scope,
api_routes = [
Route('/', landing_page),
Route('/openapi', openapi),
+ Route('/asyncapi', asyncapi),
Route('/conformance', conformance),
Route('/TileMatrixSets/{tileMatrixSetId}', get_tilematrix_set),
Route('/TileMatrixSets', get_tilematrix_sets),
diff --git a/pygeoapi/templates/asyncapi.html b/pygeoapi/templates/asyncapi.html
new file mode 100644
index 000000000..bc1915150
--- /dev/null
+++ b/pygeoapi/templates/asyncapi.html
@@ -0,0 +1,24 @@
+
+
+
+ AsyncAPI UI - {{ config['metadata']['identification']['title'] }}
+
+
+
+
+
+
+
+
diff --git a/pygeoapi/templates/landing_page.html b/pygeoapi/templates/landing_page.html
index 06f55fda9..cde2a9b1f 100644
--- a/pygeoapi/templates/landing_page.html
+++ b/pygeoapi/templates/landing_page.html
@@ -106,6 +106,17 @@ {% trans %}API Definition{% endtrans %}
{% trans %}OpenAPI Document{% endtrans %}
+ {% if data['pubsub']['asyncapi'] %}
+
+ {% endif %}
{% trans %}Conformance{% endtrans %}
diff --git a/pygeoapi/util.py b/pygeoapi/util.py
index 61f658452..44406e5b5 100644
--- a/pygeoapi/util.py
+++ b/pygeoapi/util.py
@@ -249,7 +249,7 @@ def str2bool(value: Union[bool, str]) -> bool:
def to_json(dict_: dict, pretty: bool = False) -> str:
"""
- Serialize dict to json
+ Serialize dict to JSON
:param dict_: `dict` of JSON representation
:param pretty: `bool` of whether to prettify JSON (default is `False`)
diff --git a/tests/api/test_pubsub.py b/tests/api/test_pubsub.py
index 2c30ec4cd..243c4661d 100644
--- a/tests/api/test_pubsub.py
+++ b/tests/api/test_pubsub.py
@@ -44,8 +44,8 @@ def config():
return yaml_load(fh)
-def test_landing_page(config, openapi):
- api_ = API(config, openapi)
+def test_landing_page(config, openapi, asyncapi):
+ api_ = API(config, openapi, asyncapi)
broker_link = None
@@ -54,6 +54,8 @@ def test_landing_page(config, openapi):
content = json.loads(response)
+ assert len(content['links']) == 15
+
for link in content['links']:
if link.get('rel') == 'hub':
broker_link = link
@@ -63,7 +65,7 @@ def test_landing_page(config, openapi):
assert broker_link['channel'] == 'my/channel'
config2 = deepcopy(config)
- config2['pubsub']['broker']['show_link'] = False
+ config2['pubsub']['broker']['hidden'] = True
api_ = API(config2, openapi)
@@ -74,6 +76,8 @@ def test_landing_page(config, openapi):
content = json.loads(response)
+ assert len(content['links']) == 12
+
for link in content['links']:
if link.get('rel') == 'hub':
broker_link = link
@@ -83,7 +87,7 @@ def test_landing_page(config, openapi):
config2 = deepcopy(config)
config2['pubsub']['broker'].pop('channel', None)
- api_ = API(config2, openapi)
+ api_ = API(config2, openapi, asyncapi)
broker_link = None
@@ -92,6 +96,8 @@ def test_landing_page(config, openapi):
content = json.loads(response)
+ assert len(content['links']) == 15
+
for link in content['links']:
if link.get('rel') == 'hub':
broker_link = link
diff --git a/tests/conftest.py b/tests/conftest.py
index d17a7107d..b9eef7b63 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -52,6 +52,12 @@ def openapi():
return yaml_load(fh)
+@pytest.fixture()
+def asyncapi():
+ with open(get_test_file_path('pygeoapi-test-asyncapi.yml')) as fh:
+ return yaml_load(fh)
+
+
@pytest.fixture()
def api_(config, openapi):
return API(config, openapi)
diff --git a/tests/pygeoapi-test-asyncapi.yml b/tests/pygeoapi-test-asyncapi.yml
new file mode 100644
index 000000000..1e7d1292a
--- /dev/null
+++ b/tests/pygeoapi-test-asyncapi.yml
@@ -0,0 +1,56 @@
+asyncapi: 3.0.0
+channels:
+ notify-canada-metadata:
+ address: collections/canada-metadata
+ description: Open Canada sample data
+ messages:
+ DefaultMessage:
+ payload:
+ $ref: https://raw.githubusercontent.com/wmo-im/wis2-monitoring-events/refs/heads/main/schemas/cloudevents-v1.0.2.yaml
+ notify-heif-sample:
+ address: collections/heif-sample
+ description: HEIF sample
+ messages:
+ DefaultMessage:
+ payload:
+ $ref: https://raw.githubusercontent.com/wmo-im/wis2-monitoring-events/refs/heads/main/schemas/cloudevents-v1.0.2.yaml
+defaultContentType: application/json
+id: http://localhost:5000
+info:
+ contact:
+ email: you@example.org
+ name: Lastname, Firstname
+ description: pygeoapi provides an API to geospatial data https://github.com
+ externalDocs:
+ url: https://github.com/geopython/demo.pygeoapi.io/tree/master/services/pygeoapi_cite
+ license:
+ name: CC-BY 4.0 license
+ url: https://creativecommons.org/licenses/by/4.0/
+ tags:
+ - name: geospatial
+ - name: data
+ - name: api
+ title: pygeoapi default instance
+ version: 0.23.dev0
+operations:
+ consume-canada-metadata:
+ action: receive
+ channel:
+ $ref: '#/channels/notify-canada-metadata'
+ consume-heif-sample:
+ action: receive
+ channel:
+ $ref: '#/channels/notify-heif-sample'
+ publish-canada-metadata:
+ action: send
+ channel:
+ $ref: '#/channels/notify-canada-metadata'
+ publish-heif-sample:
+ action: send
+ channel:
+ $ref: '#/channels/notify-heif-sample'
+servers:
+ default:
+ description: pygeoapi provides an API to geospatial data https://github.com
+ host: localhost:1883
+ protocol: mqtt
From 4c1a87ff0120bf70f1df4eefff98fe3f27c4d44c Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Thu, 29 Jan 2026 01:08:39 -0500
Subject: [PATCH 08/10] fix tests
---
pygeoapi/api/__init__.py | 4 ++--
pygeoapi/templates/landing_page.html | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/pygeoapi/api/__init__.py b/pygeoapi/api/__init__.py
index 07fcd8f61..ffc0a8810 100644
--- a/pygeoapi/api/__init__.py
+++ b/pygeoapi/api/__init__.py
@@ -533,7 +533,7 @@ class API:
"""API object"""
def __init__(self, config: dict, openapi: dict,
- asyncapi: dict = None) -> Self | None:
+ asyncapi: dict = {}) -> Self | None:
"""
constructor
@@ -753,7 +753,7 @@ def landing_page(api: API,
fcm['links'].append(pubsub_link)
- if api.asyncapi is not None:
+ if api.asyncapi:
fcm['links'].append({
'rel': 'service-doc',
'type': 'text/html',
diff --git a/pygeoapi/templates/landing_page.html b/pygeoapi/templates/landing_page.html
index cde2a9b1f..69e601787 100644
--- a/pygeoapi/templates/landing_page.html
+++ b/pygeoapi/templates/landing_page.html
@@ -106,7 +106,7 @@ {% trans %}API Definition{% endtrans %}
{% trans %}OpenAPI Document{% endtrans %}
- {% if data['pubsub']['asyncapi'] %}
+ {% if data['pubsub'] and data['pubsub']['asyncapi'] %}
{% trans %}AsyncAPI Definition{% endtrans %}
From a37bc8ac77d2eb78e97a1d9f15b2dac4952c4357 Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Thu, 29 Jan 2026 08:23:01 -0500
Subject: [PATCH 09/10] add exception handling
---
pygeoapi/api/processes.py | 8 ++++++--
pygeoapi/api/pubsub.py | 7 +++++--
pygeoapi/pubsub/http.py | 4 ++--
pygeoapi/pubsub/mqtt.py | 9 ++++++---
4 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/pygeoapi/api/processes.py b/pygeoapi/api/processes.py
index 1d90044a3..d6a477edf 100644
--- a/pygeoapi/api/processes.py
+++ b/pygeoapi/api/processes.py
@@ -534,8 +534,12 @@ def execute_process(api: API, request: APIRequest,
if api.pubsub_client is not None:
LOGGER.debug('Publishing message')
- publish_message(api.pubsub_client, api.base_url, 'process', process_id,
- job_id, response2)
+ try:
+ publish_message(api.pubsub_client, api.base_url, 'process',
+ process_id, job_id, response2)
+ except Exception as err:
+ msg = f'Could not publish message {err}'
+ LOGGER.warning(msg)
return headers, http_status, response2
diff --git a/pygeoapi/api/pubsub.py b/pygeoapi/api/pubsub.py
index 6f0b75a02..fdc528e1e 100644
--- a/pygeoapi/api/pubsub.py
+++ b/pygeoapi/api/pubsub.py
@@ -80,8 +80,11 @@ def publish_message(pubsub_client, url: str, action: str,
channel, data_)
LOGGER.debug(f'Message: {message}')
- pubsub_client.connect()
- pubsub_client.pub(channel, json.dumps(message))
+ try:
+ pubsub_client.connect()
+ pubsub_client.pub(channel, json.dumps(message))
+ except Exception as err:
+ raise RuntimeError(err)
def generate_ogc_cloudevent(type_: str, media_type: str, source: str,
diff --git a/pygeoapi/pubsub/http.py b/pygeoapi/pubsub/http.py
index c1144d847..a07c600ca 100644
--- a/pygeoapi/pubsub/http.py
+++ b/pygeoapi/pubsub/http.py
@@ -33,7 +33,7 @@
import requests
-from pygeoapi.pubsub.base import BasePubSubClient
+from pygeoapi.pubsub.base import BasePubSubClient, PubSubClientConnectionError
LOGGER = logging.getLogger(__name__)
@@ -99,7 +99,7 @@ def pub(self, channel: str, message: str, qos: int = 1) -> bool:
response = requests.post(url, auth=self.auth, json=message)
response.raise_for_status()
except Exception as err:
- LOGGER.debug(f'Message publishing failed: {err}')
+ raise PubSubClientConnectionError(err)
def __repr__(self):
return f' {self.broker_safe_url}'
diff --git a/pygeoapi/pubsub/mqtt.py b/pygeoapi/pubsub/mqtt.py
index 1c9adaf34..2afd04087 100644
--- a/pygeoapi/pubsub/mqtt.py
+++ b/pygeoapi/pubsub/mqtt.py
@@ -31,7 +31,7 @@
from paho.mqtt import client as mqtt_client
-from pygeoapi.pubsub.base import BasePubSubClient
+from pygeoapi.pubsub.base import BasePubSubClient, PubSubClientConnectionError
LOGGER = logging.getLogger(__name__)
@@ -83,8 +83,11 @@ def connect(self) -> None:
:returns: None
"""
- self.conn.connect(self.broker_url.hostname, self.port)
- LOGGER.debug('Connected to broker')
+ try:
+ self.conn.connect(self.broker_url.hostname, self.port)
+ LOGGER.debug('Connected to broker')
+ except Exception as err:
+ raise PubSubClientConnectionError(err)
def pub(self, channel: str, message: str, qos: int = 1) -> bool:
"""
From 048106c5839bcb207862e760ec0abde1b58a127a Mon Sep 17 00:00:00 2001
From: Tom Kralidis
Date: Thu, 29 Jan 2026 09:37:47 -0500
Subject: [PATCH 10/10] update docs
---
docs/source/administration.rst | 21 +++++++----
docs/source/pubsub.rst | 67 ++++++++++++++++++++++++++++++++--
2 files changed, 78 insertions(+), 10 deletions(-)
diff --git a/docs/source/administration.rst b/docs/source/administration.rst
index fcebd291b..9fe541f3a 100644
--- a/docs/source/administration.rst
+++ b/docs/source/administration.rst
@@ -24,12 +24,6 @@ To generate the OpenAPI document, run the following:
This will dump the OpenAPI document as YAML to your system's ``stdout``. To save to a file on disk, run:
-.. code-block:: bash
-
- pygeoapi openapi generate /path/to/my-pygeoapi-config.yml > /path/to/my-pygeoapi-openapi.yml
-
-You can also write to a file explicitly via the ``--output-file`` option:
-
.. code-block:: bash
pygeoapi openapi generate /path/to/my-pygeoapi-config.yml --output-file /path/to/my-pygeoapi-openapi.yml
@@ -38,7 +32,7 @@ To generate the OpenAPI document as JSON, run:
.. code-block:: bash
- pygeoapi openapi generate /path/to/my-pygeoapi-config.yml -f json > /path/to/my-pygeoapi-openapi.json
+ pygeoapi openapi generate /path/to/my-pygeoapi-config.yml --format json --output-file /path/to/my-pygeoapi-openapi.yml
.. note::
Generate as YAML or JSON? If your OpenAPI YAML definition is slow to render as JSON,
@@ -83,6 +77,11 @@ In UNIX:
# or if OpenAPI JSON
export PYGEOAPI_OPENAPI=/path/to/my-pygeoapi-openapi.json
+ # if your server supports AsyncAPI and Pub/Sub
+ export PYGEOAPI_ASYNCAPI=/path/to/my-pygeoapi-asyncapi.yml
+ # or if AsyncAPI JSON
+ export PYGEOAPI_ASYNCAPI=/path/to/my-pygeoapi-asyncapi.json
+
In Windows:
.. code-block:: bat
@@ -92,6 +91,14 @@ In Windows:
# or if OpenAPI JSON
set PYGEOAPI_OPENAPI=/path/to/my-pygeoapi-openapi.json
+ # if your server supports AsyncAPI and Pub/Sub
+ set PYGEOAPI_ASYNCAPI=/path/to/my-pygeoapi-asyncapi.yml
+ # or if AsyncAPI JSON
+ set PYGEOAPI_ASYNCAPI=/path/to/my-pygeoapi-asyncapi.json
+
+.. note::
+
+ More information on AsyncAPI and Pub/Sub can be found at :ref:`pubsub`.
Summary
-------
diff --git a/docs/source/pubsub.rst b/docs/source/pubsub.rst
index 5465b8171..da8570f97 100644
--- a/docs/source/pubsub.rst
+++ b/docs/source/pubsub.rst
@@ -23,10 +23,70 @@ When enabled, core functionality of Pub/Sub includes:
- feature or record transactions (create, replace, update, delete)
- process executions/job creation
-The following message queuing protocols are supported:
+AsyncAPI
+--------
+
+`AsyncAPI`_ is the event-driven equivalent to :ref:`openapi`
+
+The official AsyncAPI specification can be found on the `AsyncAPI`_ website. pygeoapi supports AsyncAPI version 3.0.0.
+
+AsyncAPI is an optional capability in pygeoapi. To enable AsyncAPI, the following steps are required:
+
+- defining a ``pubsub`` section in configuration (see :ref:`configuration` and :ref:`brokers` for more information)
+- generating an AsyncAPI document
+- setting the ``PYGEOAPI_ASYNCAPI`` environment variable
+
+Creating the AsyncAPI document
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The AsyncAPI document is a YAML or JSON configuration which is generated from the pygeoapi configuration, and describes the server information, channels and the message payloads structures.
+
+To generate the AsyncAPI document, run the following:
+
+.. code-block:: bash
+
+ pygeoapi asyncapi generate /path/to/my-pygeoapi-config.yml
+
+This will dump the AsyncAPI document as YAML to your system's ``stdout``. To save to a file on disk, run:
+
+.. code-block:: bash
+
+ pygeoapi asyncapi generate /path/to/my-pygeoapi-config.yml --output-file /path/to/my-pygeoapi-asyncapi.yml
+
+To generate the AsyncAPI document as JSON, run:
+
+.. code-block:: bash
+
+ pygeoapi asyncapi generate /path/to/my-pygeoapi-config.yml --format json --output-file /path/to/my-pygeoapi-asyncapi.json
+
+.. note::
+ Generate as YAML or JSON? If your AsyncAPI YAML definition is slow to render as JSON,
+ saving as JSON to disk will help with performance at run-time.
+
+.. note::
+ The AsyncAPI document provides detailed information on query parameters, and dataset
+ property names and their data types. Whenever you make changes to your pygeoapi configuration,
+ always refresh the accompanying AsyncAPI document.
+
+Validating the AsyncAPI document
+--------------------------------
+
+To ensure your AsyncAPI document is valid, pygeoapi provides a validation
+utility that can be run as follows:
+
+.. code-block:: bash
+
+ pygeoapi asyncapi validate /path/to/my-pygeoapi-asyncapi.yml
+
+.. _brokers:
+
+Brokers
+-------
+
+The following protocols are supported:
MQTT
-----
+^^^^
Example directive:
@@ -40,7 +100,7 @@ Example directive:
hidden: false # default
HTTP
-----
+^^^^
Example directive:
@@ -72,3 +132,4 @@ Example directive:
If a ``channel`` is not defined, only the relevant OGC API endpoint is used.
.. _`OGC API Publish-Subscribe Workflow - Part 1: Core`: https://docs.ogc.org/DRAFTS/25-030.html
+.. _`AsyncAPI`: https://www.asyncapi.com