diff --git a/gwcelery/tasks/avro.py b/gwcelery/tasks/avro.py
new file mode 100644
index 0000000000000000000000000000000000000000..50c42cc404051c0aef741727196e779fe059ea5e
--- /dev/null
+++ b/gwcelery/tasks/avro.py
@@ -0,0 +1,103 @@
+from ..import app
+from . import gracedb
+
+import fastavro
+import voeventparse
+from hop.models import AvroBlob
+
+# FIXME Figure out where this will live
+parsed_schema = fastavro.schema.load_schema('/home/emfollow-test/.avro_avsc_files_test_deleteme/igwn.alerts.v1_0.Alert.avsc')
+
+
+@gracedb.task(shared=False)
+def _create_alert_payload(superevent_id):
+    skymap_bytes = gracedb.download.s(
+        'bayestar.multiorder.fits',
+        superevent_id
+    )()
+    # FIXME Add check to ensure skymap downloaded correctly
+    return skymap_bytes
+
+
+def _create_alert_dict(message, raven_coinc=False):
+    # FIXME Update to extract information from igwn alert instead of voevent
+
+    alert_dict = {}
+
+    voevent = voeventparse.voevent.loads(message)
+
+    params = {elem.attrib['name']: elem.attrib['value'] for elem in
+              voevent.iterfind('.//Param')}
+    # the voevent object returns lxml.objectify.StringElement objects for
+    # fields that contain strings, need to convert this to a string for the
+    # avro writer
+    alert_dict['author'] = str(voevent.Who.Author.contactName)
+    alert_dict['alert_type'] = params['AlertType'].upper()
+    # FIXME Should the time_created field be the same as the voevent?
+    alert_dict['time_created'] = str(voevent.Who.Date)
+    alert_dict['superevent_id'] = params['GraceID']
+    alert_dict['is_public'] = bool(params['OpenAlert'])
+    # FIXME Do we need to check for software injections?
+    alert_dict['is_injection'] = bool(params['HardwareInj'])
+    alert_dict['urls'] = {'gracedb': params['EventPage']}
+    alert_dict['event_revision'] = int(params['Pkt_Ser_Num'])
+
+    if alert_dict['alert_type'] == 'RETRACTION':
+        alert_dict['event'] = None
+    else:
+        # FIXME Is there a better way to check for a skymap without querying
+        # gracedb?
+        if 'skymap_fits' in params:
+            skymap = _create_alert_payload(alert_dict['superevent_id'])
+        else:
+            skymap = None
+        alert_dict['event'] = {
+            'time': str(voevent.find('.//TimeInstant').getchildren()[0]),
+            'far': float(params['FAR']),
+            'instruments': sorted(params['Instruments'].split(',')),
+            'group': params['Group'],
+            'pipeline': params['Pipeline'],
+            'search': params['Search'],
+            'classification': {
+                'BNS': float(params['BNS']),
+                'NSBH': float(params['NSBH']),
+                'BBH': float(params['BBH'])
+            } if params['Group'] == 'CBC' else {},
+            'properties': {
+                'HasNS': float(params['HasNS']),
+                'HasRemnant': float(params['HasRemnant'])
+            },
+            'skymap': skymap
+        }
+
+    if raven_coinc:
+        alert_dict['external_coinc'] = {
+            'gcn_notice_id': params['External_GCN_Notice_Id'],
+            'ivorn': params['External_Ivorn'],
+            'observatory': params['External_Observatory'],
+            'search': params['External_Search'],
+            'time_difference': params['Time_Difference'],
+            'time_coincidence_far': params.get(['Time_Coincidence_FAR']),
+            'time_sky_position_coincidence_far':
+            params.get(['Time_Sky_Position_Coincidence_FAR'])
+        }
+    else:
+        # FIXME Currently this logic will cause the task to silently ignore
+        # external coincs that are missing keys but otherwise are valid
+        alert_dict['external_coinc'] = None
+
+    return alert_dict
+
+
+@app.task(bind=True, default_retry_delay=20.0,
+          ignore_result=True, queue='kafka', retry_backoff=True,
+          retry_kwargs=dict(max_retries=10), shared=False)
+def send(self, message, raven_coinc=False):
+    """Send an avro alert to a kafka broker
+    """
+
+    # Create dictionary following avro schema
+    alert_dict = _create_alert_dict(message, raven_coinc)
+
+    # Write to hop stream
+    self.app.conf['hop_stream'].write(AvroBlob([alert_dict], schema=parsed_schema))
diff --git a/gwcelery/tasks/igwn_alert.py b/gwcelery/tasks/igwn_alert.py
index 3c8bc07c930bc613455f137e6f62fdace2f8ad87..86a718f192d61329f450e2c58f05267cbd7f0f03 100644
--- a/gwcelery/tasks/igwn_alert.py
+++ b/gwcelery/tasks/igwn_alert.py
@@ -1,4 +1,6 @@
 """IGWN alert client."""
+import json
+
 from celery.utils.log import get_task_logger
 
 from ..igwn_alert.signals import igwn_alert_received
@@ -18,7 +20,14 @@ class _IGWNAlertDispatchHandler(DispatchHandler):
         igwn_alert_topics.update(keys)
         return super().__call__(*keys, **kwargs)
 
-    def process_args(self, topic, alert):
+    def process_args(self, topic, message):
+        # FIXME: Loading the message with json.loads() is a change required
+        # because we are using a newer version of hop-client than IGWN-Alert
+        # is, once IGWN-Alert upgrades to the newest version the message may
+        # become a dictionary once again
+        # FIXME: Add release version of hop-client that we are using once the
+        # avro-support branch makes it into a release
+        alert = json.loads(message.content)
         # Determine GraceDB service URL
         try:
             try:
@@ -28,7 +37,7 @@ class _IGWNAlertDispatchHandler(DispatchHandler):
         except KeyError:
             log.exception(
                 'IGWN alert message does not contain an API URL: %r',
-                alert)
+                message)
             return None, None, None
         base, api, _ = self_link.partition('/api/')
         service = base + api
diff --git a/gwcelery/tasks/orchestrator.py b/gwcelery/tasks/orchestrator.py
index e7a5ff3a891a8183228f15b2ee221124f5295209..80163788d1c5f02da47eeefc3756759ce7e5b63a 100644
--- a/gwcelery/tasks/orchestrator.py
+++ b/gwcelery/tasks/orchestrator.py
@@ -10,6 +10,7 @@ import re
 from celery import group
 
 from ..import app
+from . import avro
 from . import bayestar
 from . import circulars
 from .core import identity, get_first
@@ -736,12 +737,17 @@ def preliminary_initial_update_alert(filenames, superevent_id, alert_type,
         group(
             gracedb.download.s(superevent_id)
             |
-            gcn.send.s()
-            |
-            (
-                gracedb.create_label.si('GCN_PRELIM_SENT', superevent_id)
-                if alert_type in {'earlywarning', 'preliminary'}
-                else identity.si()
+            group(
+                gcn.send.s()
+                |
+                (
+                    gracedb.create_label.si('GCN_PRELIM_SENT', superevent_id)
+                    if alert_type in {'earlywarning', 'preliminary'}
+                    else identity.si()
+                ),
+                # FIXME Create label like GCN_PRELIM_SENT on gracedb that can
+                # be set here
+                avro.send.s(raven_coinc=('RAVEN_ALERT' in labels))
             ),
 
             circular_canvas,
@@ -823,7 +829,10 @@ def retraction_alert(superevent_id):
         group(
             gracedb.download.s(superevent_id)
             |
-            gcn.send.s(),
+            group(
+                gcn.send.s(),
+                avro.send.s()
+            ),
 
             circulars.create_retraction_circular.si(superevent_id)
             |
diff --git a/gwcelery/tests/test_tasks_orchestrator.py b/gwcelery/tests/test_tasks_orchestrator.py
index 450e39554f77e138fe851cd94bb3fad37b3238cb..27da5b009a0a73d13f82bedd59984a4d2fb46a3d 100644
--- a/gwcelery/tests/test_tasks_orchestrator.py
+++ b/gwcelery/tests/test_tasks_orchestrator.py
@@ -101,7 +101,8 @@ def test_handle_superevent(monkeypatch, toy_3d_fits_filecontents,  # noqa: F811
     expose = Mock()
     plot_volume = Mock()
     plot_allsky = Mock()
-    send = Mock()
+    gcn_send = Mock()
+    avro_send = Mock()
     query_data = Mock()
     prepare_ini = Mock()
     start_pe = Mock()
@@ -114,7 +115,8 @@ def test_handle_superevent(monkeypatch, toy_3d_fits_filecontents,  # noqa: F811
     omegascan = Mock()
     check_vectors = Mock()
 
-    monkeypatch.setattr('gwcelery.tasks.gcn.send.run', send)
+    monkeypatch.setattr('gwcelery.tasks.gcn.send.run', gcn_send)
+    monkeypatch.setattr('gwcelery.tasks.avro.send.run', avro_send)
     monkeypatch.setattr('gwcelery.tasks.skymaps.plot_allsky.run', plot_allsky)
     monkeypatch.setattr('gwcelery.tasks.skymaps.plot_volume.run', plot_volume)
     monkeypatch.setattr('gwcelery.tasks.gracedb.create_tag._orig_run',
@@ -170,7 +172,8 @@ def test_handle_superevent(monkeypatch, toy_3d_fits_filecontents,  # noqa: F811
                 ProbHasNS=0.0, ProbHasRemnant=0.0, Terrestrial=0.01,
                 internal=False, open_alert=True,
                 skymap_filename='bayestar.fits.gz', skymap_type='bayestar')
-        send.assert_called_once()
+        gcn_send.assert_called_once()
+        avro_send.assert_called_once()
         create_initial_circular.assert_called_once()
 
     if alert_type == 'new' and group == 'CBC':
@@ -243,11 +246,13 @@ def superevent_initial_alert_download(filename, graceid):
 @patch('gwcelery.tasks.gracedb.download._orig_run',
        superevent_initial_alert_download)
 @patch('gwcelery.tasks.gcn.send.run')
+@patch('gwcelery.tasks.avro.send.run')
 @patch('gwcelery.tasks.circulars.create_emcoinc_circular.run')
 @patch('gwcelery.tasks.circulars.create_initial_circular.run')
 def test_handle_superevent_initial_alert(mock_create_initial_circular,
                                          mock_create_emcoinc_circular,
-                                         mock_send,
+                                         mock_gcn_send,
+                                         mock_avro_send,
                                          mock_create_voevent,
                                          mock_create_tag, mock_get_log,
                                          mock_expose, labels):
@@ -267,7 +272,8 @@ def test_handle_superevent_initial_alert(mock_create_initial_circular,
         ProbHasRemnant=0.0, Terrestrial=0.01, internal=False, open_alert=True,
         skymap_filename='foobar.fits.gz,0', skymap_type='foobar',
         raven_coinc='RAVEN_ALERT' in labels)
-    mock_send.assert_called_once_with('contents of S1234-Initial-1.xml')
+    mock_gcn_send.assert_called_once_with('contents of S1234-Initial-1.xml')
+    mock_avro_send.assert_called_once_with('contents of S1234-Initial-1.xml')
     if 'RAVEN_ALERT' in labels:
         mock_create_emcoinc_circular.assert_called_once_with('S1234')
     else:
@@ -295,9 +301,11 @@ def superevent_retraction_alert_download(filename, graceid):
 @patch('gwcelery.tasks.gracedb.download._orig_run',
        superevent_retraction_alert_download)
 @patch('gwcelery.tasks.gcn.send.run')
+@patch('gwcelery.tasks.avro.send.run')
 @patch('gwcelery.tasks.circulars.create_retraction_circular.run')
 def test_handle_superevent_retraction_alert(mock_create_retraction_circular,
-                                            mock_send,
+                                            mock_gcn_send,
+                                            mock_avro_send,
                                             mock_create_voevent,
                                             mock_create_tag, mock_expose):
     """Test that the ``ADVNO`` label triggers a retraction alert."""
@@ -312,7 +320,8 @@ def test_handle_superevent_retraction_alert(mock_create_retraction_circular,
 
     mock_create_voevent.assert_called_once_with(
         'S1234', 'retraction', internal=False, open_alert=True)
-    mock_send.assert_called_once_with('contents of S1234-Retraction-2.xml')
+    mock_gcn_send.assert_called_once_with('contents of S1234-Retraction-2.xml')
+    mock_avro_send.assert_called_once_with('contents of S1234-Retraction-2.xml')
     mock_create_retraction_circular.assert_called_once_with('S1234')
     mock_create_tag.assert_called_once_with(
         'S1234-Retraction-2.xml', 'public', 'S1234')
@@ -409,7 +418,8 @@ def test_handle_cbc_event_ignored(mock_localize,
 
 @pytest.mark.live_worker
 @patch('gwcelery.tasks.gcn.send')
-def test_alerts_skip_inj(mock_gcn_send):
+@patch('gwcelery.tasks.avro.send')
+def test_alerts_skip_inj(mock_gcn_send, mock_avro_send):
     orchestrator.preliminary_initial_update_alert.delay(
         ('bayestar.fits.gz', 'em_bright.json', 'p_astro.json'),
         'S1234',
@@ -417,6 +427,7 @@ def test_alerts_skip_inj(mock_gcn_send):
         labels=['INJ']
     ).get()
     mock_gcn_send.assert_not_called()
+    mock_avro_send.assert_not_called()
 
 
 @pytest.fixture
diff --git a/poetry.lock b/poetry.lock
index 109572dba9034895fb44909d39cd8954758e41ce..2756008e29ab336f6f87f9cad357ecefd9db4548 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -622,6 +622,20 @@ category = "dev"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "fastavro"
+version = "1.5.1"
+description = "Fast read/write of AVRO files"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+codecs = ["python-snappy", "zstandard", "lz4"]
+lz4 = ["lz4"]
+snappy = ["python-snappy"]
+zstandard = ["zstandard"]
+
 [[package]]
 name = "flask"
 version = "2.0.3"
@@ -795,14 +809,16 @@ scipy = "*"
 
 [[package]]
 name = "hop-client"
-version = "0.5.0"
+version = "0.5.1.dev46+ged47984"
 description = "A pub-sub client library for Multi-messenger Astrophysics"
 category = "main"
 optional = false
 python-versions = ">=3.6.*"
+develop = false
 
 [package.dependencies]
 adc-streaming = ">=2.0.0"
+fastavro = ">=1.4.0"
 pluggy = ">=0.11"
 toml = ">=0.9.4"
 xmltodict = ">=0.9.0"
@@ -811,6 +827,12 @@ xmltodict = ">=0.9.0"
 dev = ["autopep8", "flake8", "pytest (>=5.0,<5.4)", "pytest-console-scripts", "pytest-cov", "pytest-runner", "twine"]
 docs = ["sphinx", "sphinx-rtd-theme", "sphinxcontrib-programoutput"]
 
+[package.source]
+type = "git"
+url = "https://github.com/scimma/hop-client.git"
+reference = "avro-support"
+resolved_reference = "ed479840a945138a9e23e30b218ddc7b69c27835"
+
 [[package]]
 name = "humanize"
 version = "4.1.0"
@@ -843,20 +865,19 @@ python-versions = ">=3.5"
 
 [[package]]
 name = "igwn-alert"
-version = "0.1.3"
+version = "0.1.2"
 description = "IGWN Alert Network"
 category = "main"
 optional = false
 python-versions = ">=3.6"
 
 [package.dependencies]
-confluent-kafka = "1.7.0"
-hop-client = "0.5.0"
+hop-client = "*"
 safe-netrc = "*"
 
 [[package]]
 name = "igwn-auth-utils"
-version = "0.2.2"
+version = "0.2.3"
 description = "Authorisation utilities for IGWN"
 category = "main"
 optional = false
@@ -869,7 +890,7 @@ safe-netrc = {version = ">=1.0.0", optional = true, markers = "extra == \"reques
 scitokens = ">=1.7.0"
 
 [package.extras]
-docs = ["sphinx (>=4.0.0)", "sphinx-automodapi", "sphinx-material"]
+docs = ["sphinx (>=4.0.0)", "sphinx-immaterial-igwn"]
 lint = ["flake8 (>=3.7.0)", "flake8-bandit"]
 requests = ["requests (>=2.14)", "safe-netrc (>=1.0.0)"]
 test = ["pytest (>=3.9.1)", "pytest-cov", "requests (>=2.14)", "requests-mock", "safe-netrc (>=1.0.0)"]
@@ -990,6 +1011,14 @@ qtconsole = ["qtconsole"]
 test = ["pytest (<7.1)", "pytest-asyncio", "testpath"]
 test_extra = ["pytest (<7.1)", "pytest-asyncio", "testpath", "curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "trio"]
 
+[[package]]
+name = "iso8601"
+version = "1.0.2"
+description = "Simple module to parse ISO 8601 dates"
+category = "main"
+optional = false
+python-versions = ">=3.6.2,<4.0"
+
 [[package]]
 name = "itsdangerous"
 version = "2.1.2"
@@ -1367,6 +1396,17 @@ category = "main"
 optional = false
 python-versions = ">=3.8"
 
+[[package]]
+name = "orderedmultidict"
+version = "1.0.1"
+description = "Ordered Multivalue Dictionary"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+six = ">=1.8.0"
+
 [[package]]
 name = "p-astro"
 version = "1.0.0"
@@ -1987,7 +2027,7 @@ scipy = ">=1.0"
 
 [[package]]
 name = "sentry-sdk"
-version = "1.5.12"
+version = "1.6.0"
 description = "Python client for Sentry (https://sentry.io)"
 category = "main"
 optional = false
@@ -2368,6 +2408,26 @@ category = "main"
 optional = false
 python-versions = ">=3.6"
 
+[[package]]
+name = "voevent-parse"
+version = "1.0.3"
+description = "Convenience routines for parsing and manipulation of VOEvent XML packets."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+astropy = ">=1.2"
+iso8601 = "*"
+lxml = ">=2.3"
+orderedmultidict = "*"
+pytz = "*"
+six = "*"
+
+[package.extras]
+all = ["pytest (>3)", "coverage"]
+test = ["pytest (>3)", "coverage"]
+
 [[package]]
 name = "voeventlib"
 version = "1.2"
@@ -2457,7 +2517,7 @@ test = ["pytest-celery", "pytest-flask", "pytest-socket"]
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.8"
-content-hash = "ff986a3ffa12ac06992338825c690d4fedb2cf456275290b39a85952dae6ca08"
+content-hash = "6b98361809e461be4c0e08aed613df106fe9d7b2b53061c877460e371eca1d21"
 
 [metadata.files]
 adc-streaming = [
@@ -2787,6 +2847,21 @@ executing = [
     {file = "executing-0.8.3-py2.py3-none-any.whl", hash = "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9"},
     {file = "executing-0.8.3.tar.gz", hash = "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501"},
 ]
+fastavro = [
+    {file = "fastavro-1.5.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:920d170560198741fa196a62a97c220173339766e6c14369c5c68bfe8cdafa25"},
+    {file = "fastavro-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b00b1711511981c4e2dd4a27ba5ae20897fe41ec7ab52eda868626d445081e5"},
+    {file = "fastavro-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:04438b592980633ccf5d1de7798480a634ca581ae7575ab7671ba16773b6b428"},
+    {file = "fastavro-1.5.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:0ab92ab744f9172da0791bfad0495d785c7c4f5a68924e3c6c6b39b78b044b11"},
+    {file = "fastavro-1.5.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ca1a60cecd710ead076585b56b954ab3e6e001d8e7384cb4ed20019b29e7a9"},
+    {file = "fastavro-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b5ff657c0d48553492d8356a30b6112fcc6db69adce6bba31135272bc9d87d82"},
+    {file = "fastavro-1.5.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:0f1ed38042a2a90a7a5da170006459e73134f4c14f4fda9ebba99017adb1b14c"},
+    {file = "fastavro-1.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df83ebdd7b67b52a37bc84c6e25f7056f756fb216c5c8e5c95ae1673fcbb6015"},
+    {file = "fastavro-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:0053347a92add6f448837ff00099b0a7200ec5dd58e173743d856d65d0574ddb"},
+    {file = "fastavro-1.5.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:6b4f8551ccbe0c9b19867b8c93029e8cfe8fa3757245caae6228f35ef0656371"},
+    {file = "fastavro-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff241b5ce36df7af7461d001ca98fec6eacd56c4754c8ac7718e2d4b7b690a82"},
+    {file = "fastavro-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:fb3491c88e7962a6b820548ddd12b9c0f6296ebd2385a3021296f14bfe35189a"},
+    {file = "fastavro-1.5.1.tar.gz", hash = "sha256:0815da740ced2261f90b0ddbb5bbe645e9c893c8f00e5dc8d30b8ec20f3c7fa9"},
+]
 flask = [
     {file = "Flask-2.0.3-py3-none-any.whl", hash = "sha256:59da8a3170004800a2837844bfa84d49b022550616070f7cb1a659682b2e7c9f"},
     {file = "Flask-2.0.3.tar.gz", hash = "sha256:e1120c228ca2f553b470df4a5fa927ab66258467526069981b3eb0a91902687d"},
@@ -2855,10 +2930,7 @@ healpy = [
     {file = "healpy-1.15.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c8d7a279815446d12d6cc3e2c030d893dac785ac65f11314e2932638970c5f8"},
     {file = "healpy-1.15.2.tar.gz", hash = "sha256:d559ad287a78d3b500919a5cb9e4dff3cb63c1b3a2e23edf62819c871ccacf7f"},
 ]
-hop-client = [
-    {file = "hop-client-0.5.0.tar.gz", hash = "sha256:ea15cbfb972fc9ee208397234e6e5371df076bec1cdbacb35735b5c70731b14f"},
-    {file = "hop_client-0.5.0-py3-none-any.whl", hash = "sha256:2c355d43919b70e109b7e9bfe15646b083a156924a00b0f1e7b0e2733563f9ea"},
-]
+hop-client = []
 humanize = [
     {file = "humanize-4.1.0-py3-none-any.whl", hash = "sha256:953b393f5bd67e19d47a4c0fd20c3a3537853967b307e49729c4755d3551753c"},
     {file = "humanize-4.1.0.tar.gz", hash = "sha256:3a119b242ec872c029d8b7bf8435a61a5798f124b244a08013aec5617302f80e"},
@@ -2872,12 +2944,12 @@ idna = [
     {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
 ]
 igwn-alert = [
-    {file = "igwn-alert-0.1.3.tar.gz", hash = "sha256:c834f5dfee6ce94400346ba740dbcf53dd5d1d51c86b454fe4380503cb3e650e"},
-    {file = "igwn_alert-0.1.3-py2.py3-none-any.whl", hash = "sha256:91f9aa1effdce44c54e63e7cb2ad08e6eef90e44c8b380572c70cafe532f5610"},
+    {file = "igwn-alert-0.1.2.tar.gz", hash = "sha256:60502900f0f78805ba9098937efd8969f6ceae181ae7dbd30213d1a52ecffa48"},
+    {file = "igwn_alert-0.1.2-py2.py3-none-any.whl", hash = "sha256:b98aa1c343cdac259271ceeb7b695cdea000184ac796ed9a02e9fa3f4eb185f3"},
 ]
 igwn-auth-utils = [
-    {file = "igwn-auth-utils-0.2.2.tar.gz", hash = "sha256:96fff480f59cf143122595ecc9195d2205e24deecc90761fd3c50d34eca8a0ab"},
-    {file = "igwn_auth_utils-0.2.2-py3-none-any.whl", hash = "sha256:d153899cd2fa5d3d7212764f69ebdf2857e9ae38af52c466d3cfe27c64ecc4b1"},
+    {file = "igwn-auth-utils-0.2.3.tar.gz", hash = "sha256:17ea61ef47dd642a572e887f37f5181613d8882ed4b917b1279cdb188859de3c"},
+    {file = "igwn_auth_utils-0.2.3-py3-none-any.whl", hash = "sha256:8c26e62f59673e7bc67304768706fdae029cbd4516b9885061d417c331766710"},
 ]
 imagesize = [
     {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"},
@@ -2907,6 +2979,10 @@ ipython = [
     {file = "ipython-8.4.0-py3-none-any.whl", hash = "sha256:7ca74052a38fa25fe9bedf52da0be7d3fdd2fb027c3b778ea78dfe8c212937d1"},
     {file = "ipython-8.4.0.tar.gz", hash = "sha256:f2db3a10254241d9b447232cec8b424847f338d9d36f9a577a6192c332a46abd"},
 ]
+iso8601 = [
+    {file = "iso8601-1.0.2-py3-none-any.whl", hash = "sha256:d7bc01b1c2a43b259570bb307f057abc578786ea734ba2b87b836c5efc5bd443"},
+    {file = "iso8601-1.0.2.tar.gz", hash = "sha256:27f503220e6845d9db954fb212b95b0362d8b7e6c1b2326a87061c3de93594b1"},
+]
 itsdangerous = [
     {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
     {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"},
@@ -3231,6 +3307,10 @@ numpy = [
     {file = "numpy-1.22.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0791fbd1e43bf74b3502133207e378901272f3c156c4df4954cad833b1380207"},
     {file = "numpy-1.22.4.zip", hash = "sha256:425b390e4619f58d8526b3dcf656dde069133ae5c240229821f01b5f44ea07af"},
 ]
+orderedmultidict = [
+    {file = "orderedmultidict-1.0.1-py2.py3-none-any.whl", hash = "sha256:43c839a17ee3cdd62234c47deca1a8508a3f2ca1d0678a3bf791c87cf84adbf3"},
+    {file = "orderedmultidict-1.0.1.tar.gz", hash = "sha256:04070bbb5e87291cc9bfa51df413677faf2141c73c61d2a5f7b26bea3cd882ad"},
+]
 p-astro = [
     {file = "p_astro-1.0.0.tar.gz", hash = "sha256:810bd5413ba1bce5153a2ab2616a94530dceaa34b14699aa794702a12ecdad04"},
 ]
@@ -3762,8 +3842,8 @@ seaborn = [
     {file = "seaborn-0.11.2.tar.gz", hash = "sha256:cf45e9286d40826864be0e3c066f98536982baf701a7caa386511792d61ff4f6"},
 ]
 sentry-sdk = [
-    {file = "sentry-sdk-1.5.12.tar.gz", hash = "sha256:259535ba66933eacf85ab46524188c84dcb4c39f40348455ce15e2c0aca68863"},
-    {file = "sentry_sdk-1.5.12-py2.py3-none-any.whl", hash = "sha256:778b53f0a6c83b1ee43d3b7886318ba86d975e686cb2c7906ccc35b334360be1"},
+    {file = "sentry-sdk-1.6.0.tar.gz", hash = "sha256:b82ad57306d5546713f15d5d70daea0408cf7f998c7566db16e0e6257e51e561"},
+    {file = "sentry_sdk-1.6.0-py2.py3-none-any.whl", hash = "sha256:ddbd191b6f4e696b7845b4d87389898ae1207981faf114f968a57363aa6be03c"},
 ]
 service-identity = [
     {file = "service-identity-21.1.0.tar.gz", hash = "sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34"},
@@ -3963,6 +4043,9 @@ vine = [
     {file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"},
     {file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"},
 ]
+voevent-parse = [
+    {file = "voevent-parse-1.0.3.tar.gz", hash = "sha256:9c4f3479d6890ed9e6123aefa8e2f5dfacf711eec161bdcb3b90da70b519ba86"},
+]
 voeventlib = [
     {file = "VOEventLib-1.2-py3-none-any.whl", hash = "sha256:1d566284e250bf546d483d86d5bc34bafa73aa068a5413defcf5577128a5429d"},
     {file = "VOEventLib-1.2.tar.gz", hash = "sha256:494450715bfefc063ff552d3d259ed8434de1effa8b3ee66dc99fe887e8ff202"},
diff --git a/pyproject.toml b/pyproject.toml
index 2721479cae81d902b529c838c34d762efd480663..1994f46655933433852d3bbb540404e6e9d06647 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -92,6 +92,9 @@ sphinx = {version=">=4.0", optional=true}
 pytest-celery = {version="*", optional=true}
 pytest-flask = {version="*", optional=true}
 pytest-socket = {version="*", optional=true}
+fastavro = "^1.5.1"
+hop-client = {git = "https://github.com/scimma/hop-client.git", branch="avro-support"}
+voevent-parse = "^1.0.3"
 
 [tool.poetry.extras]
 doc = ["pep517", "sphinx"]