> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tenderly.co/llms.txt
> Use this file to discover all available pages before exploring further.

# На уровне проекта

> На этой странице описано, как создать каждое назначение оповещений (Alert Destination) на уровне проекта.

Назначения на уровне проекта доступны только внутри того проекта, в котором они были созданы.

### Web3 Actions

Этот тип назначения оповещения означает, что ваш action будет использоваться как [**назначение для оповещения**](/monitoring/web3-actions/references/notifications).

```yaml title="example.yaml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
trigger:
  type: alert
  alert: {}
```

Один action может использоваться как назначение для нескольких оповещений.

Для получения дополнительной информации [прочитайте об этом и о Web3 Actions в целом](/monitoring/web3-actions/introduction).

### Webhooks

Этот тип назначения оповещения позволяет выполнять ваш webhook при срабатывании оповещения. Ваш webhook получит подписанную полезную нагрузку, содержащую объект транзакции, которая вызвала срабатывание оповещения.

<Note>
  После добавления webhook как назначения оповещения его можно использовать как назначение для других оповещений.
</Note>

<Card title="Как использовать Webhooks для оповещений" href="" />

#### Требования к webhook:

* Он **должен** предоставлять метод **GET** по URI webhook, немедленно возвращающий `HTTP 200`. Tenderly отправляет запрос к этому методу, чтобы убедиться, что webhook доступен.
* Он **должен** предоставлять метод **POST** с тем же URI webhook. Webhook будет получать полезную нагрузку, описанную ниже.
* Если ответ `HTTP 200` не получен в течение **5 секунд**, Tenderly считает выполнение webhook неуспешным.
* URL webhook должен использовать HTTPS.

<Warning>
  Webhook должен ответить в течение **5 секунд**. Если ответа нет, выполнение
  считается неуспешным.
</Warning>

Tenderly отслеживает все выполнения. Выполнение webhook может иметь несколько статусов:

* **Success** — webhook успешно выполнен и событие доставлено на указанный URL
* **Failed** — webhook не удалось выполнить из-за ошибки, такой как проблема с соединением, ошибка в URL и т. д. (проверьте содержимое ответа, чтобы понять причину ошибки, или обратитесь в нашу поддержку)
* **Pending** — webhook находится в процессе выполнения и ещё не завершён
* **Retry** — выполнение webhook не удалось, но будет повторено не более 5 раз, пока статус не изменится на Success или Failed
* **Skipped** — webhook не был выполнен, поскольку был отключён

#### Полезная нагрузка webhook

Webhook получит полезную нагрузку, представляющую событие оповещения. Она состоит из трёх полей:

* **id**: `String` — ID, уникальный среди всех доставленных событий оповещений (UUID).
* **event\_type**: `TEST` | `ALERT` — тип события webhook.
* **transaction**: `Object` — объект, представляющий недекодированную транзакцию, вызвавшую оповещение и выполнение webhook.

После добавления webhook как назначения оповещения он будет вызван с типом события `TEST`.

<Note>
  Используйте поле `id`, чтобы гарантировать, что ваш webhook обрабатывает каждое событие оповещения ровно один раз,
  отслеживая уже обработанные ID.
</Note>

#### Защита webhook

Вы можете повысить безопасность своих webhook с помощью проверки подписи. Так вы можете убедиться, что запрос к webhook исходит от Tenderly, прежде чем продолжать выполнение.

Заголовок `x-tenderly-signature` содержит криптографическую подпись. Подпись запроса webhook — это HMAC SHA256 хеш от конкатенации секретного ключа подписи, полезной нагрузки запроса и метки времени, именно в этом порядке.

<Warning>
  Секретный ключ подписи уникален для каждого назначения webhook. Tenderly генерирует этот секрет и использует
  его для создания подписи полезной нагрузки. Храните его в безопасном месте.
</Warning>

**Шаг 1.** Получите секретный ключ подписи.

<Frame caption="Копирование секретного ключа подписи">
  <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/alerts/project-scoped-1.webp?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=07905c94a0f58a65c1829fd6928f53b7" alt="Copying secret signing key" width="3040" height="1962" data-path="images/alerts/project-scoped-1.webp" />
</Frame>

**Шаг 2.** Проверьте полученную подпись

Чтобы проверить полученную подпись, объедините в следующем порядке:

1. секретный ключ подписи,
2. всю полезную нагрузку запроса webhook,
3. метку времени (из полезной нагрузки).

Наконец, выполните хеш SHA 256 от полученного значения.

<Tabs>
  <Tab title="example.go">
    ```go title="example.go" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    func isValidSignature(
      signature string,
      payload []byte,
      timestamp string,
    ) bool {
      h := hmac.New(sha256.New, []byte(signingKey))
      h.Write(payload)
      h.Write([]byte(timestamp))
      digest := hex.EncodeToString(h.Sum(nil))
      return digest == signature
    }
    ```
  </Tab>

  <Tab title="example.js">
    ```javascript title="example.js" showLineNumbers showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    function isValidSignature(signature, payload, timestamp) {
      // Create a HMAC SHA256 hash using the signing key
      const hmac = crypto.createHmac("sha256", signingKey);

      // Update the hash with the request body using utf8
      hmac.update(payload.toString(), 'utf8');

      // Update the hash with the request timestamp
      hmac.update(timestamp);
      const digest = hmac.digest("hex");
      return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest))
    }
    ```
  </Tab>

  <Tab title="example.py">
    ```python title="example.py" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    def isValidSignature(signature: string, payload: bytes, timestamp: string):
        h = hmac.new(str.encode(signingKey), payload, hashlib.sha256)
        h.update(str.encode(timestamp))
        digest = h.hexdigest()
        return hmac.compare_digest(signature, digest)
    ```
  </Tab>
</Tabs>

#### Отладка выполнения webhook

Для облегчения отладки неисправностей webhook вы можете вручную отправлять события `TEST` на основе существующих транзакций из любой сети.

**Шаг 1.** Нажмите "**Test Webhook**" в панели навигации страницы webhooks.

<Frame caption="Обзор webhook">
  <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/alerts/project-scoped-2.webp?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=c8cbe77743e297f330933b35c2586920" alt="Webhook overview" width="3040" height="1962" data-path="images/alerts/project-scoped-2.webp" />
</Frame>

**Шаг 2.** Вставьте хеш транзакции, соответствующей триггеру вашего оповещения

<Frame caption="Тестирование webhook: вставка хеша транзакции">
  <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/alerts/project-scoped-3.webp?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=44d10fc2a14401875b0c8f4dcd86388c" alt="Testing webhook: paste the transaction hash" width="3040" height="1962" data-path="images/alerts/project-scoped-3.webp" />
</Frame>

**Шаг 3.** Нажмите "**Test Webhook**" для подтверждения и отправки тестового события.

Ваш webhook будет вызван с транзакцией, соответствующей вставленному хешу, и типом события `TEST`. Вы получите обзор этого выполнения.

<Frame caption="Результат ручного (тестового) выполнения webhook">
  <img src="https://mintcdn.com/tenderly/XsEZlaGXYskrtN68/images/alerts/project-scoped-4.webp?fit=max&auto=format&n=XsEZlaGXYskrtN68&q=85&s=aef5371f83afe692757350de5e0effbd" alt="Result of a manual (test) execution of a webhook" width="3040" height="2072" data-path="images/alerts/project-scoped-4.webp" />
</Frame>
