Open edX Webhooks
#############################
|pypi-badge| |ci-badge| |codecov-badge| |doc-badge| |pyversions-badge|
|license-badge| |status-badge|
Purpose
*******
Webhooks for Open edX
This plugin implements a generic case of events handling that
trigger a request to a configurable URL when a signal is received.
Getting Started
***************
Introduction
============
A `Webhook` is a mechanism that triggers an HTTP POST request to a configurable
URL when certain events happen in the platform, including information relevant
to the event. For example, you can make the platform call an API when a user
logs in, including the user ID and email to connect to another application.
A `Webfilter` is a special case of webhook that allows also modifying the
data and/or interrupting the process. For example, after the user login event
you can update the user full name or prevent the user to log in if it is not
allowed to.
Deploying
=========
To install this plugin into an Open edX installed by Tutor add this line
to the ``OPENEDX_EXTRA_PIP_REQUIREMENTS`` list in the ``config.yml`` file.
.. code-block::
OPENEDX_EXTRA_PIP_REQUIREMENTS:
- openedx-webhooks
If it is an existing installation, you might need to run migrations to create
the database table. For this, run:
.. code-block::
tutor {dev|local|k8s} exec lms ./manage.py lms migrate
Configuring
===========
A new section named `OPENEDX_WEBHOOKS` will be available in the LMS Django
admin site. It will contain two subsections: `Webhooks` and `Webfilters`.
Add a new webhook to define the URLs that will be called after each event is
received. More than one URL can be configured for each event. In this case,
all URLs will be called.
Configuring webhooks
--------------------
The `Webhooks` Django admin panel has the following settings:
* Description: Add a description for this webhook for reference.
* Event: Choose from the list the event that will trigger the webhook.
* Webhook URL: URL to call. Get it from your webhook processor.
* Enabled: Click to enable the webhook.
* Use WWW form encoding: When enabled, the data will be passed in a web form format. If disabled, data will be passed in JSON format.
Configuring webfilters
----------------------
The `Webfilters` Django admin panel has the following settings:
* Description: Add a description for this webhook for reference.
* Event: Choose from the list the event that will trigger the webhook.
* Webhook URL: URL to call. Get it from your webhook processor.
* Enabled: Click to enable the webhook.
* Disable filtering: If enabled, the data passed to the web filter will not be modified even if the response includes any update.
* Disable halting: If enabled, the process will not be interrupted even if the response includes an exception setting.
* Halt on 4xx: Interrupt the process if the call to the URL returns any 4xx error code.
* Redirect on 4xx: Include an URL to redirect in case of a 4xx response, if the event supports redirection.
* Halt on 5xx: Interrupt the process if the call to the URL returns any 5xx error code.
* Redirect on 5xx: Include an URL to redirect in case of a 5xx response, if the event supports redirection.
* Halt on request exception: Interrupt the process if the call to the URL results in a connection error (e.g., timeout).
* Redirect on request exception: Include an URL to redirect in case of a connection error, if the event supports redirection.
* Use WWW form encoding: When enabled, the data will be passed in a web form format. If disabled, data will be passed in JSON format.
Receiving data
--------------
Both webhooks and webfilters will trigger POST requests to the configured URL.
This request includes in the payload a structure with data relevant to the
event that triggered the call. In all cases, the payload will include an
``event_metadata`` key including at least the event type and the date and time
in UTC format. Other keys included will depend on the event. For example,
log in events usually include ``user`` and ``profile`` keys with details of the
user logging in.
If the ``Use WWW form encoding`` option is enabled, the data will be passed as
plain key-value pairs in form encoding. The structure will be flattened and the
key names will be concatenated. E.g., a log event will include ``user_id``,
``user_email``, ``event_metadata_time``, etc.
Responding to webfilters
------------------------
The webhook processor should respond to a webfilter with a data structure in
JSON format and a successful status code (200). The response can be empty or
can have one or both of these keys:
* data
* exception
Updating data
~~~~~~~~~~~~~
The corresponding objects will be updated with the values returned inside the
``data`` key. Only keys present in the response will be updated. Other keys
will remain unchanged in the original data structures. To disable data updates,
set ``Disable Filtering`` in the webfilter configuration at the Django admin
panel.
For example, to change the full name of a user at registration time, respond
to a `Student Registration Requested` webfilter with this data:
.. code-block::
{
"data": {
"form_data": {
"name": "New Name"
}
}
}
Interrupting execution
~~~~~~~~~~~~~~~~~~~~~~
To stop the process to complete, add a JSON object as value for the `exception`
key. This object must have only one key-value pair, being the key the name
of the exception to raise. Its value can be either a string representing the
message to be shown, or another JSON object with more data.
For example, to prevent a user to register, respond to the `Student
Registration Requested` webfilter with this data:
.. code-block::
{
"exception": {
"PreventRegistration": "Not allowed to register"
}
}
To prevent a webfilter to stop the execution of the process, set ``Disable
halting`` in the webfilter configuration at the Django admin
panel.
Check each function documentation to see the list of available values and
exceptions.
Handling multiple events
------------------------
If you set more than one webhook or webfilter for the same event, all of them
will be triggered. The responses of all the webfilters will be combined in one
data structure and used to update the objects. If more webfilter processors
include data for the same key, the last one will override all the previous.
Developing
==========
More information about available signals can be found in the `events documentation`_
and the `filters documentation`_
.. _events documentation: https://github.com/openedx/edx-platform/blob/master/docs/guides/hooks/events.rst
.. _filters documentation: https://github.com/openedx/edx-platform/blob/master/docs/guides/hooks/filters.rst
One Time Setup
--------------
.. code-block::
# Clone the repository
git clone git@github.com:aulasneo/openedx-webhooks.git
cd openedx-webhooks
# Set up a virtualenv with the same name as the repo and activate it
# Here's how you might do that if you have virtualenvwrapper setup.
mkvirtualenv -p python3.8 openedx-webhooks
Every time you develop something in this repo
---------------------------------------------
.. code-block::
# Activate the virtualenv
# Here's how you might do that if you're using virtualenvwrapper.
workon openedx-webhooks
# Grab the latest code
git checkout main
git pull
# Install/update the dev requirements
make requirements
# Run the tests and quality checks (to verify the status before you make any changes)
make validate
# Make a new branch for your changes
git checkout -b <your_github_username>/<short_description>
# Using your favorite editor, edit the code to make your change.
vim ...
# Run your new tests
pytest ./path/to/new/tests
# Run all the tests and quality checks
make validate
# Commit all your changes
git commit ...
git push
# Open a PR and ask for review.
Getting Help
************
If you need any help, send us an email to `info@aulasneo.com`_.
.. _info@aulasneo.com: mailto:info@aulasneo.com
More Help
=========
If you're having trouble, we have discussion forums at
https://discuss.openedx.org where you can connect with others in the
community.
Our real-time conversations are on Slack. You can request a `Slack
invitation`_, then join our `community Slack workspace`_.
For anything non-trivial, the best path is to open an issue in this
repository with as many details about the issue you are facing as you
can provide.
https://github.com/aulasneo/openedx-webhooks/issues
For more information about these options, see the `Getting Help`_ page.
.. _Slack invitation: https://openedx.org/slack
.. _community Slack workspace: https://openedx.slack.com/
.. _Getting Help: https://openedx.org/getting-help
License
*******
The code in this repository is licensed under the AGPL 3.0 unless
otherwise noted.
Please see `LICENSE.txt <LICENSE.txt>`_ for details.
Contributing
************
Contributions are very welcome.
Please read `How To Contribute <https://openedx.org/r/how-to-contribute>`_ for details.
This project is currently accepting all types of contributions, bug fixes,
security fixes, maintenance work, or new features. However, please make sure
to have a discussion about your new feature idea with the maintainers prior to
beginning development to maximize the chances of your change being accepted.
You can start a conversation by creating a new issue on this repo summarizing
your idea.
The Open edX Code of Conduct
****************************
All community members are expected to follow the `Open edX Code of Conduct`_.
.. _Open edX Code of Conduct: https://openedx.org/code-of-conduct/
People
******
The assigned maintainers for this component and other project details may be
found in `Backstage`_. Backstage pulls this data from the ``catalog-info.yaml``
file in this repo.
.. _Backstage: https://backstage.openedx.org/catalog/default/component/webhooks
Reporting Security Issues
*************************
Please do not report security issues in public. Please email security@tcril.org.
.. |pypi-badge| image:: https://img.shields.io/pypi/v/webhooks.svg
:target: https://pypi.python.org/pypi/webhooks/
:alt: PyPI
.. |ci-badge| image:: https://github.com/openedx/webhooks/workflows/Python%20CI/badge.svg?branch=main
:target: https://github.com/openedx/webhooks/actions
:alt: CI
.. |codecov-badge| image:: https://codecov.io/github/openedx/webhooks/coverage.svg?branch=main
:target: https://codecov.io/github/openedx/webhooks?branch=main
:alt: Codecov
.. |doc-badge| image:: https://readthedocs.org/projects/webhooks/badge/?version=latest
:target: https://docs.openedx.org/projects/webhooks
:alt: Documentation
.. |pyversions-badge| image:: https://img.shields.io/pypi/pyversions/webhooks.svg
:target: https://pypi.python.org/pypi/webhooks/
:alt: Supported Python versions
.. |license-badge| image:: https://img.shields.io/github/license/openedx/webhooks.svg
:target: https://github.com/openedx/webhooks/blob/main/LICENSE.txt
:alt: License
.. |status-badge| image:: https://img.shields.io/badge/Status-Experimental-yellow
.. .. |status-badge| image:: https://img.shields.io/badge/Status-Maintained-brightgreen
.. .. |status-badge| image:: https://img.shields.io/badge/Status-Deprecated-orange
.. .. |status-badge| image:: https://img.shields.io/badge/Status-Unsupported-red
Change Log
##########
Version 1.1.0 (2023-08-22)
**********************************************
* Add grade changes signals
* `COURSE_GRADE_CHANGED <https://github.com/openedx/edx-platform/blob/1d618055dc5a44b94a1da63ef4017a2015aad018/lms/djangoapps/grades/course_grade_factory.py#L201>`_
* `COURSE_GRADE_NOW_PASSED <https://github.com/openedx/edx-platform/blob/1d618055dc5a44b94a1da63ef4017a2015aad018/lms/djangoapps/grades/course_grade_factory.py#L209C17-L209C40>`_
* `COURSE_GRADE_NOW_FAILED <https://github.com/openedx/edx-platform/blob/1d618055dc5a44b94a1da63ef4017a2015aad018/lms/djangoapps/grades/course_grade_factory.py#L215C17-L215C40>`_
Version 1.0.1 (2023-08-15)
**********************************************
* Fix: remove non implemented filters
Version 1.0.0 (2023-08-15)
**********************************************
* Added webfilters:
* CertificateCreationRequested,
* CertificateRenderStarted,
* CohortAssignmentRequested,
* CohortChangeRequested,
* CourseAboutRenderStarted,
* CourseEnrollmentStarted,
* CourseUnenrollmentStarted,
* DashboardRenderStarted,
* StudentLoginRequested,
* StudentRegistrationRequested,
* Available webhooks:
* SESSION_LOGIN_COMPLETED
* STUDENT_REGISTRATION_COMPLETED
* COURSE_ENROLLMENT_CREATED
* COURSE_ENROLLMENT_CHANGED
* COURSE_UNENROLLMENT_COMPLETED
* CERTIFICATE_CREATED
* CERTIFICATE_CHANGED
* CERTIFICATE_REVOKED
* COHORT_MEMBERSHIP_CHANGED
* COURSE_DISCUSSIONS_CHANGED
Version 0.2.1 (2023-06-06)
**********************************************
* Renamed package to openedx_webhooks. Upload to PyPI.
Version 0.1.1 (2023-06-05)
**********************************************
* Improve documentation
0.1.0 – 2023-05-31
**********************************************
Added
=====
* First release on PyPI.
Raw data
{
"_id": null,
"home_page": "https://github.com/aulasneo/openedx-webhooks",
"name": "openedx-webhooks",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "Openedx webhooks",
"author": "Aulasneo",
"author_email": "andres@aulasneo.com",
"download_url": "https://files.pythonhosted.org/packages/46/62/94f73520a179e300776df6a552003cc807d8d89163d6037d84e03e6c5c00/openedx_webhooks-1.1.0.tar.gz",
"platform": null,
"description": "Open edX Webhooks\n#############################\n\n|pypi-badge| |ci-badge| |codecov-badge| |doc-badge| |pyversions-badge|\n|license-badge| |status-badge|\n\nPurpose\n*******\n\nWebhooks for Open edX\n\nThis plugin implements a generic case of events handling that\ntrigger a request to a configurable URL when a signal is received.\n\nGetting Started\n***************\n\nIntroduction\n============\n\nA `Webhook` is a mechanism that triggers an HTTP POST request to a configurable\nURL when certain events happen in the platform, including information relevant\nto the event. For example, you can make the platform call an API when a user\nlogs in, including the user ID and email to connect to another application.\n\nA `Webfilter` is a special case of webhook that allows also modifying the\ndata and/or interrupting the process. For example, after the user login event\nyou can update the user full name or prevent the user to log in if it is not\nallowed to.\n\nDeploying\n=========\n\nTo install this plugin into an Open edX installed by Tutor add this line\nto the ``OPENEDX_EXTRA_PIP_REQUIREMENTS`` list in the ``config.yml`` file.\n\n.. code-block::\n\n OPENEDX_EXTRA_PIP_REQUIREMENTS:\n - openedx-webhooks\n\nIf it is an existing installation, you might need to run migrations to create\nthe database table. For this, run:\n\n.. code-block::\n\n tutor {dev|local|k8s} exec lms ./manage.py lms migrate\n\nConfiguring\n===========\n\nA new section named `OPENEDX_WEBHOOKS` will be available in the LMS Django\nadmin site. It will contain two subsections: `Webhooks` and `Webfilters`.\nAdd a new webhook to define the URLs that will be called after each event is\nreceived. More than one URL can be configured for each event. In this case,\nall URLs will be called.\n\nConfiguring webhooks\n--------------------\n\nThe `Webhooks` Django admin panel has the following settings:\n\n* Description: Add a description for this webhook for reference.\n* Event: Choose from the list the event that will trigger the webhook.\n* Webhook URL: URL to call. Get it from your webhook processor.\n* Enabled: Click to enable the webhook.\n* Use WWW form encoding: When enabled, the data will be passed in a web form format. If disabled, data will be passed in JSON format.\n\nConfiguring webfilters\n----------------------\n\nThe `Webfilters` Django admin panel has the following settings:\n\n* Description: Add a description for this webhook for reference.\n* Event: Choose from the list the event that will trigger the webhook.\n* Webhook URL: URL to call. Get it from your webhook processor.\n* Enabled: Click to enable the webhook.\n* Disable filtering: If enabled, the data passed to the web filter will not be modified even if the response includes any update.\n* Disable halting: If enabled, the process will not be interrupted even if the response includes an exception setting.\n* Halt on 4xx: Interrupt the process if the call to the URL returns any 4xx error code.\n* Redirect on 4xx: Include an URL to redirect in case of a 4xx response, if the event supports redirection.\n* Halt on 5xx: Interrupt the process if the call to the URL returns any 5xx error code.\n* Redirect on 5xx: Include an URL to redirect in case of a 5xx response, if the event supports redirection.\n* Halt on request exception: Interrupt the process if the call to the URL results in a connection error (e.g., timeout).\n* Redirect on request exception: Include an URL to redirect in case of a connection error, if the event supports redirection.\n* Use WWW form encoding: When enabled, the data will be passed in a web form format. If disabled, data will be passed in JSON format.\n\nReceiving data\n--------------\n\nBoth webhooks and webfilters will trigger POST requests to the configured URL.\nThis request includes in the payload a structure with data relevant to the\nevent that triggered the call. In all cases, the payload will include an\n``event_metadata`` key including at least the event type and the date and time\nin UTC format. Other keys included will depend on the event. For example,\nlog in events usually include ``user`` and ``profile`` keys with details of the\nuser logging in.\n\nIf the ``Use WWW form encoding`` option is enabled, the data will be passed as\nplain key-value pairs in form encoding. The structure will be flattened and the\nkey names will be concatenated. E.g., a log event will include ``user_id``,\n``user_email``, ``event_metadata_time``, etc.\n\nResponding to webfilters\n------------------------\n\nThe webhook processor should respond to a webfilter with a data structure in\nJSON format and a successful status code (200). The response can be empty or\ncan have one or both of these keys:\n\n* data\n* exception\n\nUpdating data\n~~~~~~~~~~~~~\n\nThe corresponding objects will be updated with the values returned inside the\n``data`` key. Only keys present in the response will be updated. Other keys\nwill remain unchanged in the original data structures. To disable data updates,\nset ``Disable Filtering`` in the webfilter configuration at the Django admin\npanel.\n\nFor example, to change the full name of a user at registration time, respond\nto a `Student Registration Requested` webfilter with this data:\n\n.. code-block::\n\n {\n \"data\": {\n \"form_data\": {\n \"name\": \"New Name\"\n }\n }\n }\n\nInterrupting execution\n~~~~~~~~~~~~~~~~~~~~~~\n\nTo stop the process to complete, add a JSON object as value for the `exception`\nkey. This object must have only one key-value pair, being the key the name\nof the exception to raise. Its value can be either a string representing the\nmessage to be shown, or another JSON object with more data.\n\nFor example, to prevent a user to register, respond to the `Student\nRegistration Requested` webfilter with this data:\n\n.. code-block::\n\n {\n \"exception\": {\n \"PreventRegistration\": \"Not allowed to register\"\n }\n }\n\nTo prevent a webfilter to stop the execution of the process, set ``Disable\nhalting`` in the webfilter configuration at the Django admin\npanel.\n\nCheck each function documentation to see the list of available values and\nexceptions.\n\nHandling multiple events\n------------------------\n\nIf you set more than one webhook or webfilter for the same event, all of them\nwill be triggered. The responses of all the webfilters will be combined in one\ndata structure and used to update the objects. If more webfilter processors\ninclude data for the same key, the last one will override all the previous.\n\nDeveloping\n==========\n\n\nMore information about available signals can be found in the `events documentation`_\nand the `filters documentation`_\n\n.. _events documentation: https://github.com/openedx/edx-platform/blob/master/docs/guides/hooks/events.rst\n.. _filters documentation: https://github.com/openedx/edx-platform/blob/master/docs/guides/hooks/filters.rst\n\n\nOne Time Setup\n--------------\n.. code-block::\n\n # Clone the repository\n git clone git@github.com:aulasneo/openedx-webhooks.git\n cd openedx-webhooks\n\n # Set up a virtualenv with the same name as the repo and activate it\n # Here's how you might do that if you have virtualenvwrapper setup.\n mkvirtualenv -p python3.8 openedx-webhooks\n\n\nEvery time you develop something in this repo\n---------------------------------------------\n.. code-block::\n\n # Activate the virtualenv\n # Here's how you might do that if you're using virtualenvwrapper.\n workon openedx-webhooks\n\n # Grab the latest code\n git checkout main\n git pull\n\n # Install/update the dev requirements\n make requirements\n\n # Run the tests and quality checks (to verify the status before you make any changes)\n make validate\n\n # Make a new branch for your changes\n git checkout -b <your_github_username>/<short_description>\n\n # Using your favorite editor, edit the code to make your change.\n vim ...\n\n # Run your new tests\n pytest ./path/to/new/tests\n\n # Run all the tests and quality checks\n make validate\n\n # Commit all your changes\n git commit ...\n git push\n\n # Open a PR and ask for review.\n\nGetting Help\n************\n\nIf you need any help, send us an email to `info@aulasneo.com`_.\n\n.. _info@aulasneo.com: mailto:info@aulasneo.com\n\nMore Help\n=========\n\nIf you're having trouble, we have discussion forums at\nhttps://discuss.openedx.org where you can connect with others in the\ncommunity.\n\nOur real-time conversations are on Slack. You can request a `Slack\ninvitation`_, then join our `community Slack workspace`_.\n\nFor anything non-trivial, the best path is to open an issue in this\nrepository with as many details about the issue you are facing as you\ncan provide.\n\nhttps://github.com/aulasneo/openedx-webhooks/issues\n\nFor more information about these options, see the `Getting Help`_ page.\n\n.. _Slack invitation: https://openedx.org/slack\n.. _community Slack workspace: https://openedx.slack.com/\n.. _Getting Help: https://openedx.org/getting-help\n\nLicense\n*******\n\nThe code in this repository is licensed under the AGPL 3.0 unless\notherwise noted.\n\nPlease see `LICENSE.txt <LICENSE.txt>`_ for details.\n\nContributing\n************\n\nContributions are very welcome.\nPlease read `How To Contribute <https://openedx.org/r/how-to-contribute>`_ for details.\n\nThis project is currently accepting all types of contributions, bug fixes,\nsecurity fixes, maintenance work, or new features. However, please make sure\nto have a discussion about your new feature idea with the maintainers prior to\nbeginning development to maximize the chances of your change being accepted.\nYou can start a conversation by creating a new issue on this repo summarizing\nyour idea.\n\nThe Open edX Code of Conduct\n****************************\n\nAll community members are expected to follow the `Open edX Code of Conduct`_.\n\n.. _Open edX Code of Conduct: https://openedx.org/code-of-conduct/\n\nPeople\n******\n\nThe assigned maintainers for this component and other project details may be\nfound in `Backstage`_. Backstage pulls this data from the ``catalog-info.yaml``\nfile in this repo.\n\n.. _Backstage: https://backstage.openedx.org/catalog/default/component/webhooks\n\nReporting Security Issues\n*************************\n\nPlease do not report security issues in public. Please email security@tcril.org.\n\n.. |pypi-badge| image:: https://img.shields.io/pypi/v/webhooks.svg\n :target: https://pypi.python.org/pypi/webhooks/\n :alt: PyPI\n\n.. |ci-badge| image:: https://github.com/openedx/webhooks/workflows/Python%20CI/badge.svg?branch=main\n :target: https://github.com/openedx/webhooks/actions\n :alt: CI\n\n.. |codecov-badge| image:: https://codecov.io/github/openedx/webhooks/coverage.svg?branch=main\n :target: https://codecov.io/github/openedx/webhooks?branch=main\n :alt: Codecov\n\n.. |doc-badge| image:: https://readthedocs.org/projects/webhooks/badge/?version=latest\n :target: https://docs.openedx.org/projects/webhooks\n :alt: Documentation\n\n.. |pyversions-badge| image:: https://img.shields.io/pypi/pyversions/webhooks.svg\n :target: https://pypi.python.org/pypi/webhooks/\n :alt: Supported Python versions\n\n.. |license-badge| image:: https://img.shields.io/github/license/openedx/webhooks.svg\n :target: https://github.com/openedx/webhooks/blob/main/LICENSE.txt\n :alt: License\n\n.. |status-badge| image:: https://img.shields.io/badge/Status-Experimental-yellow\n.. .. |status-badge| image:: https://img.shields.io/badge/Status-Maintained-brightgreen\n.. .. |status-badge| image:: https://img.shields.io/badge/Status-Deprecated-orange\n.. .. |status-badge| image:: https://img.shields.io/badge/Status-Unsupported-red\n\n\nChange Log\n##########\n\nVersion 1.1.0 (2023-08-22)\n**********************************************\n\n* Add grade changes signals\n * `COURSE_GRADE_CHANGED <https://github.com/openedx/edx-platform/blob/1d618055dc5a44b94a1da63ef4017a2015aad018/lms/djangoapps/grades/course_grade_factory.py#L201>`_\n * `COURSE_GRADE_NOW_PASSED <https://github.com/openedx/edx-platform/blob/1d618055dc5a44b94a1da63ef4017a2015aad018/lms/djangoapps/grades/course_grade_factory.py#L209C17-L209C40>`_\n * `COURSE_GRADE_NOW_FAILED <https://github.com/openedx/edx-platform/blob/1d618055dc5a44b94a1da63ef4017a2015aad018/lms/djangoapps/grades/course_grade_factory.py#L215C17-L215C40>`_\n\n\nVersion 1.0.1 (2023-08-15)\n**********************************************\n\n* Fix: remove non implemented filters\n\nVersion 1.0.0 (2023-08-15)\n**********************************************\n\n* Added webfilters:\n * CertificateCreationRequested,\n * CertificateRenderStarted,\n * CohortAssignmentRequested,\n * CohortChangeRequested,\n * CourseAboutRenderStarted,\n * CourseEnrollmentStarted,\n * CourseUnenrollmentStarted,\n * DashboardRenderStarted,\n * StudentLoginRequested,\n * StudentRegistrationRequested,\n\n* Available webhooks:\n * SESSION_LOGIN_COMPLETED\n * STUDENT_REGISTRATION_COMPLETED\n * COURSE_ENROLLMENT_CREATED\n * COURSE_ENROLLMENT_CHANGED\n * COURSE_UNENROLLMENT_COMPLETED\n * CERTIFICATE_CREATED\n * CERTIFICATE_CHANGED\n * CERTIFICATE_REVOKED\n * COHORT_MEMBERSHIP_CHANGED\n * COURSE_DISCUSSIONS_CHANGED\n\n\nVersion 0.2.1 (2023-06-06)\n**********************************************\n\n* Renamed package to openedx_webhooks. Upload to PyPI.\n\nVersion 0.1.1 (2023-06-05)\n**********************************************\n\n* Improve documentation\n\n0.1.0 \u2013 2023-05-31\n**********************************************\n\nAdded\n=====\n\n* First release on PyPI.\n",
"bugtrack_url": null,
"license": "AGPL 3.0",
"summary": "Webhooks for Open edX",
"version": "1.1.0",
"project_urls": {
"Homepage": "https://github.com/aulasneo/openedx-webhooks"
},
"split_keywords": [
"openedx",
"webhooks"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "6d1e3e66bffb46c79696e3db67aa911400a4692fd31feda6315ffb7276686f39",
"md5": "a11d549eb0cde280c1f86b359b92255a",
"sha256": "faa9ae47b2387d6bcf6d5798050a49563777026f1b2fddb5f10124b2adba975b"
},
"downloads": -1,
"filename": "openedx_webhooks-1.1.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "a11d549eb0cde280c1f86b359b92255a",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": ">=3.8",
"size": 43926,
"upload_time": "2023-08-22T16:06:56",
"upload_time_iso_8601": "2023-08-22T16:06:56.683022Z",
"url": "https://files.pythonhosted.org/packages/6d/1e/3e66bffb46c79696e3db67aa911400a4692fd31feda6315ffb7276686f39/openedx_webhooks-1.1.0-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "466294f73520a179e300776df6a552003cc807d8d89163d6037d84e03e6c5c00",
"md5": "2c9ee6daa5796d557f8c7d0e663a8eb4",
"sha256": "58f8ce76f58022b0e726cca341ba03b2dd3518c6dec1cc96d7d9a874ed8523c9"
},
"downloads": -1,
"filename": "openedx_webhooks-1.1.0.tar.gz",
"has_sig": false,
"md5_digest": "2c9ee6daa5796d557f8c7d0e663a8eb4",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 44591,
"upload_time": "2023-08-22T16:06:58",
"upload_time_iso_8601": "2023-08-22T16:06:58.969801Z",
"url": "https://files.pythonhosted.org/packages/46/62/94f73520a179e300776df6a552003cc807d8d89163d6037d84e03e6c5c00/openedx_webhooks-1.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-08-22 16:06:58",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "aulasneo",
"github_project": "openedx-webhooks",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"tox": true,
"lcname": "openedx-webhooks"
}