diff --git a/site/content/en/docs/administration/advanced/webhooks.md b/site/content/en/docs/administration/advanced/webhooks.md new file mode 100644 index 00000000..b6615ed7 --- /dev/null +++ b/site/content/en/docs/administration/advanced/webhooks.md @@ -0,0 +1,366 @@ +--- +title: 'Webhooks' +linkTitle: 'Webhooks' +description: 'Instructions for working with CVAT Webhooks' +weight: 80 +--- + +## Create Webhook + +In CVAT you can create webhook for project or for organization. +For creation, you can use our user interface or direct API calls. + +In order to create webhook via an API call, see the [swagger documentation](https://app.cvat.ai/api/docs). +And also see examples of creating webhooks in our [REST API tests](https://github.com/opencv/cvat/blob/develop/tests/python/rest_api/test_webhooks.py). + +### Create Webhook for project + +To create webhook for CVAT project, follow the steps: + +`Project -> Actions -> Setup Webhooks` + +![](/images/create_project_webhook.gif) + +### Create Webhook for organization + +To create webhook for CVAT organization, follow the steps: + +`Organization -> Settings -> Actions -> Setup Webhooks` + +![](/images/create_organization_webhook.gif) + +## List of available events + +| Resource | Create | Update | Delete | +| :---: | :----: | :----: | :----: | +| Organization | | ✅ | | +| Membership | | ✅ | ✅ | +| Invitation | ✅ | | ✅ | +| Project | ✅ | ✅ | ✅ | +| Task | ✅ | ✅ | ✅ | +| Job | | ✅ | | +| Issue | ✅ | ✅ | ✅ | +| Comment | ✅ | ✅ | ✅ | + +## Payloads + +### Create event + +Webhook payload object for `create:` events: + +| Key | Type | Description | +| :---: | :----: | :---- | +| `event` | `string` | Name of event that triggered webhook with pattern `create:` | +| `` | `object` | Full information about created resource. See the swagger docs for each separate resource | +| `webhook_id` | `integer` | Identifier of webhook that sent payload | +| `sender` | `object` | Information about user that triggered webhook | + +Here is example of payload for `create:task` event: +{{< scroll-code lang="json" >}} +{ + "event": "create:task", + "task": { + "url": "", + "id": 15, + "name": "task", + "project_id": 7, + "mode": "", + "owner": { + "url": "", + "id": 1, + "username": "admin1", + "first_name": "Admin", + "last_name": "First" + }, + "assignee": null, + "bug_tracker": "", + "created_date": "2022-10-04T08:05:50.419259Z", + "updated_date": "2022-10-04T08:05:50.422917Z", + "overlap": null, + "segment_size": 0, + "status": "annotation", + "labels": \[ + { + "id": 28, + "name": "label_0", + "color": "#bde94a", + "attributes": [], + "type": "any", + "sublabels": [], + "has_parent": false + } + \], + "segments": [], + "dimension": "2d", + "subset": "", + "organization": null, + "target_storage": { + "id": 14, + "location": "local", + "cloud_storage_id": null + }, + "source_storage": { + "id": 13, + "location": "local", + "cloud_storage_id": null + } + }, + "webhook_id": 7, + "sender": { + "url": "", + "id": 1, + "username": "admin1", + "first_name": "Admin", + "last_name": "First" + } +} +{{< /scroll-code >}} + + +### Update event + +Webhook payload object for `update:` events: + +| Key | Type | Description | +| :---: | :----: | :---- | +| `event` | `string` | Name of event that triggered webhook with pattern `update:` | +| `` | `object` | Full information about updated resource. See the swagger docs for each separate resource | +| `before_update` | `object` | Keys of `` that was updated with theirs old values | +| `webhook_id` | `integer` | Identifier of webhook that sent payload | +| `sender` | `object` | Information about user that triggered webhook | + +{{< scroll-code lang="json" >}} +{ + "event": "update:task", + "task": { + "url": "", + "id": 15, + "name": "new task name", + "project_id": 7, + "mode": "annotation", + "owner": { + "url": "", + "id": 1, + "username": "admin1", + "first_name": "Admin", + "last_name": "First" + }, + "assignee": null, + "bug_tracker": "", + "created_date": "2022-10-04T08:05:50.419259Z", + "updated_date": "2022-10-04T11:04:51.451681Z", + "overlap": 0, + "segment_size": 1, + "status": "annotation", + "labels": \[ + { + "id": 28, + "name": "label_0", + "color": "#bde94a", + "attributes": [], + "type": "any", + "sublabels": [], + "has_parent": false + } + \], + "segments": \[ + { + "start_frame": 0, + "stop_frame": 0, + "jobs": \[ + { + "url": "", + "id": 19, + "assignee": null, + "status": "annotation", + "stage": "annotation", + "state": "new" + } + \] + } + \], + "data_chunk_size": 14, + "data_compressed_chunk_type": "imageset", + "data_original_chunk_type": "imageset", + "size": 1, + "image_quality": 70, + "data": 14, + "dimension": "2d", + "subset": "", + "organization": null, + "target_storage": { + "id": 14, + "location": "local", + "cloud_storage_id": null + }, + "source_storage": { + "id": 13, + "location": "local", + "cloud_storage_id": null + } + }, + "before_update": { + "name": "task" + }, + "webhook_id": 7, + "sender": { + "url": "", + "id": 1, + "username": "admin1", + "first_name": "Admin", + "last_name": "First" + } +} +{{< /scroll-code >}} +### Delete event + +Webhook payload object for `delete:` events: + +| Key | Type | Description | +| :---: | :----: | :---- | +| `event` | `string` | Name of event that triggered webhook with pattern `delete:` | +| `` | `object` | Full information about deleted resource. See the swagger docs for each separate resource | +| `webhook_id` | `integer` | Identifier of webhook that sent payload | +| `sender` | `object` | Information about user that triggered webhook | + +Here is example of payload for `delete:task` event: +{{< scroll-code lang="json" >}} +{ + "event": "delete:task", + "task": { + "url": "", + "id": 15, + "name": "task", + "project_id": 7, + "mode": "", + "owner": { + "url": "", + "id": 1, + "username": "admin1", + "first_name": "Admin", + "last_name": "First" + }, + "assignee": null, + "bug_tracker": "", + "created_date": "2022-10-04T08:05:50.419259Z", + "updated_date": "2022-10-04T08:05:50.422917Z", + "overlap": null, + "segment_size": 0, + "status": "annotation", + "labels": \[ + { + "id": 28, + "name": "label_0", + "color": "#bde94a", + "attributes": [], + "type": "any", + "sublabels": [], + "has_parent": false + } + \], + "segments": [], + "dimension": "2d", + "subset": "", + "organization": null, + "target_storage": { + "id": 14, + "location": "local", + "cloud_storage_id": null + }, + "source_storage": { + "id": 13, + "location": "local", + "cloud_storage_id": null + } + }, + "webhook_id": 7, + "sender": { + "url": "", + "id": 1, + "username": "admin1", + "first_name": "Admin", + "last_name": "First" + } +} +{{< /scroll-code >}} + +## Webhook secret + +To be ensure that webhooks come from CVAT you can specify `secret` when creating a webhook. + +If you specified `secret` value for webhook, then CVAT will sent webhook with `X-Signature-256` in +request header. + +CVAT encode request body for webhook using SHA256 hash function and put the result into the header. + +Webhook receiver can check that request came from CVAT by comparison received value of `X-Signature-256` with expected. + +Example of header value for empty request body and `secret = mykey`: + +``` +X-Signature-256: e1b24265bf2e0b20c81837993b4f1415f7b68c503114d100a40601eca6a2745f +``` + +## Ping Webhook + +To check that webhook configured well and CVAT can connect with target URL you can use `ping` webhook. + +After pressing `Ping` bottom on UI (or sending `POST /webhooks/{id}/ping` request) CVAT will sent webhook +to the target url with general information about webhook. + +Ping webhook payload: + +| Key | Type | Description | +| :---: | :----: | :---- | +| `event` | `string` | Value always equals `ping` | +| `webhook` | `object` | Full information about webhook. See the full description of webhook`s fields in swagger docs | +| `sender` | `object` | Information about user that called `ping` webhook | + +{{< scroll-code lang="json" >}} +{ + "event": "ping", + "webhook": { + "id": 7, + "url": "", + "target_url": "", + "description": "", + "type": "project", + "content_type": "application/json", + "is_active": true, + "enable_ssl": true, + "created_date": "2022-10-04T08:05:23.007381Z", + "updated_date": "2022-10-04T08:05:23.007395Z", + "owner": { + "url": "", + "id": 1, + "username": "admin1", + "first_name": "Admin", + "last_name": "First" + }, + "project": 7, + "organization": null, + "events": \[ + "create:comment", + "create:issue", + "create:task", + "delete:comment", + "delete:issue", + "delete:task", + "update:comment", + "update:issue", + "update:job", + "update:project", + "update:task" + \], + "last_status": 200, + "last_delivery_date": "2022-10-04T11:04:52.538638Z" + }, + "sender": { + "url": "", + "id": 1, + "username": "admin1", + "first_name": "Admin", + "last_name": "First" + } +} +{{< /scroll-code >}} diff --git a/site/content/en/images/create_organization_webhook.gif b/site/content/en/images/create_organization_webhook.gif new file mode 100644 index 00000000..2a184750 Binary files /dev/null and b/site/content/en/images/create_organization_webhook.gif differ diff --git a/site/content/en/images/create_project_webhook.gif b/site/content/en/images/create_project_webhook.gif new file mode 100644 index 00000000..373c5007 Binary files /dev/null and b/site/content/en/images/create_project_webhook.gif differ diff --git a/site/layouts/shortcodes/scroll-code.html b/site/layouts/shortcodes/scroll-code.html new file mode 100644 index 00000000..6dfe2560 --- /dev/null +++ b/site/layouts/shortcodes/scroll-code.html @@ -0,0 +1,12 @@ +
+ {{ $lang := "" }} + + {{ with $.Get "lang" }} + {{ $lang = $.Get "lang" }} + {{ end }} + + {{ $highlight := "" }} +
+ {{- highlight $.Inner $lang $highlight -}} +
+
\ No newline at end of file