> ## 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.

# Using Alerts API

> Configure simple and compound alerting rules programmatically with the Tenderly Alerts API, covering each expression type and multi-condition combinations.

This guide covers setting up both simple and complex alerting rules using Tenderly's API. We'll explore each expression type and then combine them into sophisticated monitoring solutions.

<Card title="Alerting API reference" href="/api-reference" />

## Introduction

Tenderly's Alert API allows you to create simple and complex Alerts.
A simple alert consists of one rule, for example `method_call` will get triggered when a transaction invokes your public or external method. A complex alert can have several conditions, and will get triggered when all of them are met. For example, an alert with `method_call` and `state_change` will trigger when a transaction calls the given method and updates the specified storage slot.

When defining an Alert using the API, you need to specify the following:

* **delivery channels** that get notified when alerting rule is triggered. See more about [Delivery Channels](/api-reference).
* **expressions** array that will trigger the alert when all conditions represented by individual expressions are met.

<Note>
  Email, Discord, and Sentry delivery channels can be created via the API (`POST /api/v1/account/{accountId}/delivery-channel`). Slack, Telegram, and PagerDuty channels require the OAuth/bot connection flow and can be created only via the Dashboard. All channels can be fetched using the [API](/api-reference).
</Note>

## Authentication

Before creating alerts, you'll need to set up authentication and identify your project:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const TENDERLY_API_KEY = 'your_api_key';
    const PROJECT_SLUG = 'your_project_slug';
    const ACCOUNT_ID = 'me';  // Use 'me' or your specific account ID

    // Base configuration for axios
    const baseConfig = {
      baseURL: 'https://api.tenderly.co/api/v1',
      headers: {
        'X-Access-Key': TENDERLY_API_KEY,
        'Content-Type': 'application/json'
      }
    };
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    export TENDERLY_API_KEY="your_api_key"
    export PROJECT_SLUG="your_project_slug"
    export ACCOUNT_ID="me"  # Use 'me' or your specific account ID
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import requests

    TENDERLY_API_KEY = 'your_api_key'
    PROJECT_SLUG = 'your_project_slug'
    ACCOUNT_ID = 'me'  # Use 'me' or your specific account ID

    # Base configuration for requests
    base_url = 'https://api.tenderly.co/api/v1'
    headers = {
        'X-Access-Key': TENDERLY_API_KEY,
        'Content-Type': 'application/json'
    }
    ```
  </Tab>
</Tabs>

## Expression Types

You can use different expression types for specifying Alerts' trigger rules.

| Expression Type | Monitoring | Main Use Case | Required Arguments | Optional Arguments |
| - | - | - | - | - |
| `method_call` | Specific function calls in contracts (direct or internal transactions apply) | Track when important functions are called | - `address`: Contract address; `signature`: Object with `function_name` and `input_types` (ordered ABI input types, e.g. `["address", "uint256"]`) | - `transaction_type`: "any" (default), "direct", "source", or "internal"; `parameter_conditions`: Array of conditions; `not`: boolean |
| `whitelisted_caller_addresses` | For calls from specific addresses | Allow-list based access control | - `addresses`: Array of Ethereum addresses | None |
| `blacklisted_caller_addresses` | For calls from blocked addresses | Block-list based access control | - `addresses`: Array of Ethereum addresses | None |
| `contract_address` | Specific contract interactions | Track all interactions with a contract | - `address`: Contract address | - `transaction_type`: "direct", "source", or "internal"; when omitted, both direct and internal calls match |
| `network` | Events on specific networks | Multi-chain monitoring | - `network_id`: Network/chain ID | None |
| `tag` | Contracts with specific tags | Group-based monitoring | - `tag`: Tag string | - `transaction_type`: "direct", "source", or "internal"; when omitted, behaves like "internal" |
| `tx_status` | Transaction success/failure | Track failed transactions | None | - `transaction_success`: boolean |
| `tx_value` | Transaction value | Track large transfers | - `transaction_value`: Amount in wei; `operator`: Comparison operator | None |
| `emitted_log` | Contract events | Track specific events | - `address`: Contract address; `event_name`: Event name; `event_id`: Event signature | - `match_any`: boolean (match logs from any contract); `match_non_project_contracts`: boolean; `decode_events`: boolean; `parameter_conditions`: Array of conditions; `not`: boolean |
| `state_change` | Contract state changes | Track storage changes | - `address`: Contract address; `parameter_conditions`: Array of conditions | - `match_any`: boolean (match state changes on any contract); `match_non_project_contracts`: boolean; `not`: boolean; comparison options (threshold, percentage) |
| `view_function` | Read-only function results | Track computed values | - `address`: Contract address; `input`: ABI encoded function data; `network_id`: Network ID | - `parameter_condition`: Value comparison; `not`: boolean |
| `eth_balance` | ETH balance changes | Track balance thresholds | - `address`: Contract address; `threshold`: Balance in wei | - `operator`: Comparison operator (default `<=`); `not`: boolean |
| `erc20_transfer_matcher` | ERC20 transfer consistency | Validate transfer mechanics | - `address`: Token address; `log_name`: Event name; `balances`: State variable name | None |
| `erc20_token_transfer` | ERC-20 tokens sent or received by watched addresses | Track token inflows and outflows | One of: `addresses`: Array of watched addresses; `match_any`: `true` (every project address) | - `address_tag`: string (with `match_any`); `token_addresses`: Array of `{network_id, address}`; `token_tag`: string; `match_non_project_contracts`: boolean; `require_dollar_value`: boolean (with `match_non_project_contracts`); `direction`: "any" (default), "received", or "sent"; `min_amount`, `max_amount`: raw token units as strings; `net`: boolean |

### Notes

* These are all the expression types the API accepts. A payload with any other `type` value is rejected with a `400` ("Expressions are not in the right format").
* All expressions within an alert are AND-ed: the alert fires only when every expression matches the same transaction. To monitor independent conditions, create a separate alert for each.
* For comparison operators (`operator`), valid values are: `>`, `>=`, `<`, `<=`, `==`, `!=`, `contains`, `notContains`
* Parameter types (`parameter_type`) include: `uint`, `int`, `bool`, `address`, `string`, `slice`, `array`, `tuple`, `fixed_bytes`, `bytes`, `hash`, `function`
* The expression types `emitted_log`, `erc20_transfer_matcher`, `eth_balance`, `tx_value`, `method_call`, `state_change`, `tx_status`, and `view_function` support an optional `not: true` field that negates the match
* `erc20_token_transfer` rules: set either `addresses` or `match_any`, not both. `address_tag` narrows `match_any` to tagged project addresses. With no `token_addresses`, the token scope is the project's ERC-20 contracts (narrowed by `token_tag`, or widened to any token by `match_non_project_contracts`). `require_dollar_value: true` skips transfers of tokens without a known USD price and is accepted only with `match_non_project_contracts`. `min_amount` and `max_amount` are inclusive, compare the absolute amount, and require exactly one entry in `token_addresses`. With `net: true`, direction and amount apply to the net balance change per address and token in the transaction. See [ERC-20 token transfer monitoring](#5-erc-20-token-transfer-monitoring).
* `eth_balance` fires only when a transaction moves the balance across the threshold (from non-matching to matching), not on every transaction while the condition holds
* All addresses must be valid Ethereum addresses (`0x` prefixed, 40 hex chars)
* Wei values should be passed as strings to handle large numbers
* Network IDs should match the target blockchain (e.g., "1" for Ethereum mainnet)

For more details, explore the [Alerting API reference](/api-reference).

## Simple expressions examples

Explore examples of setting up simple expression rules.

### 1. Method Call Monitoring

**Use Case**: Monitor specific function calls in your smart contract.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const methodCallAlert = {
      name: "Critical Function Call Alert",
      description: "Monitors calls to critical functions",
      enabled: true,
      expressions: [{
        type: "method_call",
        expression: {
          address: "0xe592427a0aece92de3edee1f18e0157c05861564",
          signature: {
            function_name: "unwrapWETH9", // name of the function to match
            input_types: ["uint256", "address"] // ordered ABI input types
          }
        }
      },
      {
          "type": "contract_address",
          "expression": {
              "address": "0xe592427a0aece92de3edee1f18e0157c05861564"
          }
      }
      ],
      delivery_channels: [{
        id: "your_channel_id",
        enabled: true
      }]
    };

    await axios.post(
      `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
      methodCallAlert,
      baseConfig
    );
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Critical Function Call Alert",
      "description": "Monitors calls to critical functions",
      "enabled": true,
      "expressions": [
        {
        "type": "method_call",
          "expression": {
            "address": "0xe592427a0aece92de3edee1f18e0157c05861564",
            "signature": {
              "function_name": "unwrapWETH9",
              "input_types": ["uint256", "address"]
            }
          }
        },
        {
          "type": "contract_address",
          "expression": {
              "address": "0xe592427a0aece92de3edee1f18e0157c05861564"
          }
        }
      ],
      "delivery_channels": [{
        "id": "your_channel_id",
        "enabled": true
      }]
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    method_call_alert = {
        "name": "Critical Function Call Alert",
        "description": "Monitors calls to critical functions",
        "enabled": True,
        "expressions": [{
            "type": "method_call",
            "expression": {
                "address": "0xe592427a0aece92de3edee1f18e0157c05861564",
                "signature": {
                    "function_name": "unwrapWETH9",
                    "input_types": ["uint256", "address"]
                }
            }
        },
         {
              "type": "contract_address",
              "expression": {
                  "address": "0xe592427a0aece92de3edee1f18e0157c05861564"
              }
            }],
        "delivery_channels": [{
            "id": "your_channel_id",
            "enabled": True
        }]
    }

    response = requests.post(
        f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
        headers=headers,
        json=method_call_alert
    )
    ```
  </Tab>
</Tabs>

### 2. State Change Monitoring

**Use Case**: Monitor changes in contract state variables, especially useful for tracking critical parameters like paused state or balance thresholds.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const stateChangeAlert = {
      name: "Critical State Change Alert",
      description: "Monitors important state changes",
      enabled: true,
      expressions: [{
        type: "state_change",
        expression: {
          address: "0x1234....",
          parameter_conditions: [
            {
              parameter_name: "pause",
              parameter_type: "bool",
              compare_change: true
            },
            {
              parameter_name: "totalSupply",
              parameter_type: "uint",
              compare_percentage: true,
              comparison_value: "5",
              operator: ">="
            }
          ]
        }
      }],
      delivery_channels: [{
        id: "your_channel_id",
        enabled: true
      }]
    };

    await axios.post(
      `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
      stateChangeAlert,
      baseConfig
    );
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Critical State Change Alert",
      "description": "Monitors important state changes",
      "enabled": true,
      "expressions": [{
        "type": "state_change",
        "expression": {
          "address": "0x1234....",
          "parameter_conditions": [
            {
              "parameter_name": "pause",
              "parameter_type": "bool",
              "compare_change": true
            },
            {
              "parameter_name": "totalSupply",
              "parameter_type": "uint",
              "compare_percentage": true,
              "comparison_value": "5",
              "operator": ">="
            }
          ]
        }
      }],
      "delivery_channels": [{
        "id": "your_channel_id",
        "enabled": true
      }]
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    state_change_alert = {
        "name": "Critical State Change Alert",
        "description": "Monitors important state changes",
        "enabled": True,
        "expressions": [{
            "type": "state_change",
            "expression": {
                "address": "0x1234....",
                "parameter_conditions": [
                    {
                        "parameter_name": "pause",
                        "parameter_type": "bool",
                        "compare_change": True
                    },
                    {
                        "parameter_name": "totalSupply",
                        "parameter_type": "uint",
                        "compare_percentage": True,
                        "comparison_value": "5",
                        "operator": ">="
                    }
                ]
            }
        }],
        "delivery_channels": [{
            "id": "your_channel_id",
            "enabled": True
        }]
    }

    response = requests.post(
        f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
        headers=headers,
        json=state_change_alert
    )
    ```
  </Tab>
</Tabs>

### 3. Event Monitoring

**Use Case**: Monitor specific events emitted by your contracts, with parameter filtering.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const eventAlert = {
      name: "Large Transfer Event Alert",
      description: "Monitors large transfer events",
      enabled: true,
      expressions: [{
        type: "emitted_log",
        expression: {
          address: "0x1234....",
          event_name: "Transfer",
          event_id: "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80",
          parameter_conditions: [
            {
              parameter_name: "amount",
              parameter_type: "uint",
              operator: ">=",
              comparison_value: "1000000000000000000" // 1 ETH
            }
          ],
          decode_events: true
        }
      }],
      delivery_channels: [{
        id: "your_channel_id",
        enabled: true
      }]
    };

    await axios.post(
      `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
      eventAlert,
      baseConfig
    );
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Large Transfer Event Alert",
      "description": "Monitors large transfer events",
      "enabled": true,
      "expressions": [{
        "type": "emitted_log",
        "expression": {
          "address": "0x1234....",
          "event_name": "Transfer",
          "event_id": "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80",
          "parameter_conditions": [
            {
              "parameter_name": "amount",
              "parameter_type": "uint",
              "operator": ">=",
              "comparison_value": "1000000000000000000"
            }
          ],
          "decode_events": true
        }
      }],
      "delivery_channels": [{
        "id": "your_channel_id",
        "enabled": true
      }]
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    event_alert = {
        "name": "Large Transfer Event Alert",
        "description": "Monitors large transfer events",
        "enabled": True,
        "expressions": [{
            "type": "emitted_log",
            "expression": {
                "address": "0x1234....",
                "event_name": "Transfer",
                "event_id": "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80",
                "parameter_conditions": [
                    {
                        "parameter_name": "amount",
                        "parameter_type": "uint",
                        "operator": ">=",
                        "comparison_value": "1000000000000000000"
                    }
                ],
                "decode_events": True
            }
        }],
        "delivery_channels": [{
            "id": "your_channel_id",
            "enabled": True
        }]
    }

    response = requests.post(
        f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
        headers=headers,
        json=event_alert
    )
    ```
  </Tab>
</Tabs>

### 4. Native ETH Balance Monitoring

**Use Case**: Alert when an address's native ETH balance falls below a threshold, for example a relayer or operations wallet that must stay funded. Scope the alert to a network and an address, then compare the native balance against the threshold (in wei).

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const balanceAlert = {
      name: "Low ETH balance alert",
      description: "Alerts when the native ETH balance falls below 0.1 ETH",
      enabled: true,
      expressions: [
        // Scope to a specific network
        {
          type: "network",
          expression: {
            network_id: "1" // Ethereum mainnet
          }
        },
        // Scope to the watched address
        {
          type: "contract_address",
          expression: {
            address: "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"
          }
        },
        // Trigger when the native balance drops below the threshold
        {
          type: "eth_balance",
          expression: {
            address: "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b",
            threshold: "100000000000000000", // 0.1 ETH in wei
            operator: "<"
          }
        }
      ],
      delivery_channels: [{
        id: "your_channel_id",
        enabled: true
      }]
    };

    await axios.post(
      `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
      balanceAlert,
      baseConfig
    );
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Low ETH balance alert",
      "description": "Alerts when the native ETH balance falls below 0.1 ETH",
      "enabled": true,
      "expressions": [
        {
          "type": "network",
          "expression": {
            "network_id": "1"
          }
        },
        {
          "type": "contract_address",
          "expression": {
            "address": "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"
          }
        },
        {
          "type": "eth_balance",
          "expression": {
            "address": "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b",
            "threshold": "100000000000000000",
            "operator": "<"
          }
        }
      ],
      "delivery_channels": [{
        "id": "your_channel_id",
        "enabled": true
      }]
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    balance_alert = {
        "name": "Low ETH balance alert",
        "description": "Alerts when the native ETH balance falls below 0.1 ETH",
        "enabled": True,
        "expressions": [
            {
                "type": "network",
                "expression": {
                    "network_id": "1"
                }
            },
            {
                "type": "contract_address",
                "expression": {
                    "address": "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"
                }
            },
            {
                "type": "eth_balance",
                "expression": {
                    "address": "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b",
                    "threshold": "100000000000000000",
                    "operator": "<"
                }
            }
        ],
        "delivery_channels": [{
            "id": "your_channel_id",
            "enabled": True
        }]
    }

    response = requests.post(
        f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
        headers=headers,
        json=balance_alert
    )
    ```
  </Tab>
</Tabs>

### 5. ERC-20 Token Transfer Monitoring

**Use Case**: Alert when a treasury wallet sends at least 100,000 USDT on Ethereum mainnet. The `network` expression pins the alert to one network, and `min_amount` is in raw units (USDT has 6 decimals). [ERC20 Token Transfer](/monitoring/alerts/types#erc20-token-transfer) describes each field.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const transferAlert = {
      name: "Treasury USDT outflow",
      description: "Treasury sent 100,000 USDT or more",
      enabled: true,
      expressions: [
        // Scope to a specific network
        {
          type: "network",
          expression: {
            network_id: "1" // Ethereum mainnet
          }
        },
        {
          type: "erc20_token_transfer",
          expression: {
            addresses: ["0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"],
            token_addresses: [
              { network_id: "1", address: "0xdac17f958d2ee523a2206206994597c13d831ec7" } // USDT
            ],
            direction: "sent",
            min_amount: "100000000000", // 100,000 USDT (6 decimals)
            net: true
          }
        }
      ],
      delivery_channels: [{
        id: "your_channel_id",
        enabled: true
      }]
    };

    await axios.post(
      `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
      transferAlert,
      baseConfig
    );
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Treasury USDT outflow",
      "description": "Treasury sent 100,000 USDT or more",
      "enabled": true,
      "expressions": [
        {
          "type": "network",
          "expression": {
            "network_id": "1"
          }
        },
        {
          "type": "erc20_token_transfer",
          "expression": {
            "addresses": ["0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"],
            "token_addresses": [
              { "network_id": "1", "address": "0xdac17f958d2ee523a2206206994597c13d831ec7" }
            ],
            "direction": "sent",
            "min_amount": "100000000000",
            "net": true
          }
        }
      ],
      "delivery_channels": [{
        "id": "your_channel_id",
        "enabled": true
      }]
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    transfer_alert = {
        "name": "Treasury USDT outflow",
        "description": "Treasury sent 100,000 USDT or more",
        "enabled": True,
        "expressions": [
            {
                "type": "network",
                "expression": {
                    "network_id": "1"
                }
            },
            {
                "type": "erc20_token_transfer",
                "expression": {
                    "addresses": ["0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"],
                    "token_addresses": [
                        {"network_id": "1", "address": "0xdac17f958d2ee523a2206206994597c13d831ec7"}
                    ],
                    "direction": "sent",
                    "min_amount": "100000000000",
                    "net": True
                }
            }
        ],
        "delivery_channels": [{
            "id": "your_channel_id",
            "enabled": True
        }]
    }

    response = requests.post(
        f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
        headers=headers,
        json=transfer_alert
    )
    ```
  </Tab>
</Tabs>

To watch every project address instead of one, replace `addresses` with `"match_any": true`, optionally with `"address_tag"`. To cover every project token, omit `token_addresses`; amount bounds require a single token, so remove `min_amount` and `max_amount` as well.

To match any ERC-20 token, including tokens not added to the project, omit `token_addresses` and set `"match_non_project_contracts": true`. Add `"require_dollar_value": true` to skip tokens without a known USD price, such as spam and airdropped tokens. This expression fires when any priced ERC-20 token leaves a project address tagged `treasury`:

```json theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{
  "type": "erc20_token_transfer",
  "expression": {
    "match_any": true,
    "address_tag": "treasury",
    "match_non_project_contracts": true,
    "require_dollar_value": true,
    "direction": "sent"
  }
}
```

## Complex Alert Examples

Explore examples of showing complex expression rules. The alert will get triggered when every expression in the `expressions` array is satisfied.

### 1. Security Monitoring System

**Use Case**: Comprehensive security monitoring combining multiple conditions:

* Monitor admin function calls
* Track large value transfers
* Watch for blacklisted addresses
* Alert on state changes to critical parameters

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const securityAlert = {
      name: "Security Monitoring System",
      description: "Comprehensive security monitoring for contract",
      enabled: true,
      expressions: [
        {
          "type": "contract_address",
          "expression": {
              "address": "0xe592427a0aece92de3edee1f18e0157c05861564"
          }
        },
        // Admin function monitoring
        {
          type: "method_call",
          expression: {
            address: "0xe592427a0aece92de3edee1f18e0157c05861564",
            signature: {
              function_name: "transferOwnership",
              input_types: ["address"]
            }
          }
        },
        // Blacklist checking
        {
          type: "blacklisted_caller_addresses",
          expression: {
            addresses: [
              "0xblacklisted1...",
              "0xblacklisted2..."
            ]
          }
        },
        // Large value transfers
        {
          type: "tx_value",
          expression: {
            transaction_value: "100000000000000000000", // 100 ETH
            operator: ">"
          }
        },
        // Critical state changes
        {
          type: "state_change",
          expression: {
            address: "0x1234....",
            parameter_conditions: [
              {
                parameter_name: "pause",
                parameter_type: "bool",
                compare_change: true
              },
              {
                parameter_name: "owner",
                parameter_type: "address",
                compare_change: true
              }
            ]
          }
        }
      ],
      delivery_channels: [{
        id: "your_channel_id",
        enabled: true
      }]
    };

    await axios.post(
      `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
      securityAlert,
      baseConfig
    );
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Security Monitoring System",
      "description": "Comprehensive security monitoring for contract",
      "enabled": true,
      "expressions": [
       {
          "type": "contract_address",
          "expression": {
              "address": "0xe592427a0aece92de3edee1f18e0157c05861564"
          }
        },
        {
          "type": "method_call",
          "expression": {
            "address": "0xe592427a0aece92de3edee1f18e0157c05861564",
            "signature": {
              "function_name": "transferOwnership",
              "input_types": ["address"]
            }
          }
        },
        {
          "type": "blacklisted_caller_addresses",
          "expression": {
            "addresses": [
              "0xblacklisted1...",
              "0xblacklisted2..."
            ]
          }
        },
        {
          "type": "tx_value",
          "expression": {
            "transaction_value": "100000000000000000000",
            "operator": ">"
          }
        },
        {
          "type": "state_change",
          "expression": {
            "address": "0x1234....",
            "parameter_conditions": [
              {
                "parameter_name": "pause",
                "parameter_type": "bool",
                "compare_change": true
              },
              {
                "parameter_name": "owner",
                "parameter_type": "address",
                "compare_change": true
              }
            ]
          }
        }
      ],
      "delivery_channels": [{
        "id": "your_channel_id",
        "enabled": true
      }]
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    security_alert = {
        "name": "Security Monitoring System",
        "description": "Comprehensive security monitoring for contract",
        "enabled": True,
        "expressions": [
         {
            "type": "contract_address",
            "expression": {
                "address": "0xe592427a0aece92de3edee1f18e0157c05861564"
            }
          },
            {
                "type": "method_call",
                "expression": {
                    "address": "0xe592427a0aece92de3edee1f18e0157c05861564",
                    "signature": {
                        "function_name": "transferOwnership",
                        "input_types": ["address"]
                    }
                }
            },
            {
                "type": "blacklisted_caller_addresses",
                "expression": {
                    "addresses": [
                        "0xblacklisted1...",
                        "0xblacklisted2..."
                    ]
                }
            },
            {
                "type": "tx_value",
                "expression": {
                    "transaction_value": "100000000000000000000",
                    "operator": ">"
                }
            },
            {
                "type": "state_change",
                "expression": {
                    "address": "0x1234....",
                    "parameter_conditions": [
                        {
                            "parameter_name": "pause",
                            "parameter_type": "bool",
                            "compare_change": True
                        },
                        {
                            "parameter_name": "owner",
                            "parameter_type": "address",
                            "compare_change": True
                        }
                    ]
                }
            }
        ],
        "delivery_channels": [{
            "id": "your_channel_id",
            "enabled": True
        }]
    }

    response = requests.post(
        f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
        headers=headers,
        json=security_alert
    )
    ```
  </Tab>
</Tabs>

### 2. DeFi Protocol Monitor

**Use Case**: Monitor a DeFi pool for:

* Large trades/swaps
* Liquidity changes
* Failed transactions

Because expressions within an alert are AND-ed, each condition is a separate alert. The examples below create three alerts in one go.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const defiAlerts = [
      // Alert 1: large swaps via events
      {
        name: "Large Swaps",
        description: "Swap events moving 1000+ tokens out of the pool",
        enabled: true,
        expressions: [{
          type: "emitted_log",
          expression: {
            address: "0xpool_address",
            event_name: "Swap",
            event_id: "0x...", // Swap event signature
            parameter_conditions: [
              {
                parameter_name: "amountOut",
                parameter_type: "uint",
                operator: ">=",
                comparison_value: "1000000000000000000000" // 1000 tokens
              }
            ],
            decode_events: true
          }
        }],
        delivery_channels: [{ id: "your_channel_id", enabled: true }]
      },
      // Alert 2: liquidity changes
      {
        name: "Liquidity Shift",
        description: "Pool reserves moved by 10% or more",
        enabled: true,
        expressions: [{
          type: "state_change",
          expression: {
            address: "0xpool_address",
            parameter_conditions: [
              {
                parameter_name: "reserve0",
                parameter_type: "uint",
                compare_percentage: true,
                comparison_value: "10",
                operator: ">="
              },
              {
                parameter_name: "reserve1",
                parameter_type: "uint",
                compare_percentage: true,
                comparison_value: "10",
                operator: ">="
              }
            ]
          }
        }],
        delivery_channels: [{ id: "your_channel_id", enabled: true }]
      },
      // Alert 3: failed transactions on the pool
      {
        name: "Failed Transactions",
        description: "Failed transactions involving the pool",
        enabled: true,
        expressions: [
          {
            type: "contract_address",
            expression: { address: "0xpool_address" }
          },
          {
            type: "tx_status",
            expression: { transaction_success: false }
          }
        ],
        delivery_channels: [{ id: "your_channel_id", enabled: true }]
      }
    ];

    for (const alert of defiAlerts) {
      await axios.post(
        `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
        alert,
        baseConfig
      );
    }
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    # Alert 1: large swaps via events
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Large Swaps",
      "description": "Swap events moving 1000+ tokens out of the pool",
      "enabled": true,
      "expressions": [{
        "type": "emitted_log",
        "expression": {
          "address": "0xpool_address",
          "event_name": "Swap",
          "event_id": "0x...",
          "parameter_conditions": [
            {
              "parameter_name": "amountOut",
              "parameter_type": "uint",
              "operator": ">=",
              "comparison_value": "1000000000000000000000"
            }
          ],
          "decode_events": true
        }
      }],
      "delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
    }'

    # Alert 2: liquidity changes
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Liquidity Shift",
      "description": "Pool reserves moved by 10% or more",
      "enabled": true,
      "expressions": [{
        "type": "state_change",
        "expression": {
          "address": "0xpool_address",
          "parameter_conditions": [
            {
              "parameter_name": "reserve0",
              "parameter_type": "uint",
              "compare_percentage": true,
              "comparison_value": "10",
              "operator": ">="
            },
            {
              "parameter_name": "reserve1",
              "parameter_type": "uint",
              "compare_percentage": true,
              "comparison_value": "10",
              "operator": ">="
            }
          ]
        }
      }],
      "delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
    }'

    # Alert 3: failed transactions on the pool
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Failed Transactions",
      "description": "Failed transactions involving the pool",
      "enabled": true,
      "expressions": [
        {
          "type": "contract_address",
          "expression": { "address": "0xpool_address" }
        },
        {
          "type": "tx_status",
          "expression": { "transaction_success": false }
        }
      ],
      "delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    defi_alerts = [
        # Alert 1: large swaps via events
        {
            "name": "Large Swaps",
            "description": "Swap events moving 1000+ tokens out of the pool",
            "enabled": True,
            "expressions": [{
                "type": "emitted_log",
                "expression": {
                    "address": "0xpool_address",
                    "event_name": "Swap",
                    "event_id": "0x...",
                    "parameter_conditions": [
                        {
                            "parameter_name": "amountOut",
                            "parameter_type": "uint",
                            "operator": ">=",
                            "comparison_value": "1000000000000000000000"
                        }
                    ],
                    "decode_events": True
                }
            }],
            "delivery_channels": [{"id": "your_channel_id", "enabled": True}]
        },
        # Alert 2: liquidity changes
        {
            "name": "Liquidity Shift",
            "description": "Pool reserves moved by 10% or more",
            "enabled": True,
            "expressions": [{
                "type": "state_change",
                "expression": {
                    "address": "0xpool_address",
                    "parameter_conditions": [
                        {
                            "parameter_name": "reserve0",
                            "parameter_type": "uint",
                            "compare_percentage": True,
                            "comparison_value": "10",
                            "operator": ">="
                        },
                        {
                            "parameter_name": "reserve1",
                            "parameter_type": "uint",
                            "compare_percentage": True,
                            "comparison_value": "10",
                            "operator": ">="
                        }
                    ]
                }
            }],
            "delivery_channels": [{"id": "your_channel_id", "enabled": True}]
        },
        # Alert 3: failed transactions on the pool
        {
            "name": "Failed Transactions",
            "description": "Failed transactions involving the pool",
            "enabled": True,
            "expressions": [
                {
                    "type": "contract_address",
                    "expression": {"address": "0xpool_address"}
                },
                {
                    "type": "tx_status",
                    "expression": {"transaction_success": False}
                }
            ],
            "delivery_channels": [{"id": "your_channel_id", "enabled": True}]
        }
    ]

    for alert in defi_alerts:
        response = requests.post(
            f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
            headers=headers,
            json=alert
        )
    ```
  </Tab>
</Tabs>

### 3. ERC20 Token Monitor

**Use Case**: Token monitoring including:

* Transfer consistency checks
* Large transfer monitoring
* Total supply changes

Like the previous example, each condition is its own alert.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const tokenAlerts = [
      // Alert 1: Transfer event consistency
      {
        name: "Transfer Consistency",
        description: "Transfer events inconsistent with balance changes",
        enabled: true,
        expressions: [{
          type: "erc20_transfer_matcher",
          expression: {
            address: "0xtoken_address",
            log_name: "Transfer",
            balances: "balances"
          }
        }],
        delivery_channels: [{ id: "your_channel_id", enabled: true }]
      },
      // Alert 2: large transfers
      {
        name: "Large Transfers",
        description: "Transfers of 1000+ tokens",
        enabled: true,
        expressions: [{
          type: "emitted_log",
          expression: {
            address: "0xtoken_address",
            event_name: "Transfer",
            event_id: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
            parameter_conditions: [
              {
                parameter_name: "value",
                parameter_type: "uint",
                operator: ">=",
                comparison_value: "1000000000000000000000" // 1000 tokens
              }
            ]
          }
        }],
        delivery_channels: [{ id: "your_channel_id", enabled: true }]
      },
      // Alert 3: total supply changes
      {
        name: "Supply Change",
        description: "totalSupply moved by 1% or more",
        enabled: true,
        expressions: [{
          type: "state_change",
          expression: {
            address: "0xtoken_address",
            parameter_conditions: [
              {
                parameter_name: "totalSupply",
                parameter_type: "uint",
                compare_percentage: true,
                comparison_value: "1",
                operator: ">="
              }
            ]
          }
        }],
        delivery_channels: [{ id: "your_channel_id", enabled: true }]
      }
    ];

    for (const alert of tokenAlerts) {
      await axios.post(
        `/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
        alert,
        baseConfig
      );
    }
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    # Alert 1: Transfer event consistency
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Transfer Consistency",
      "description": "Transfer events inconsistent with balance changes",
      "enabled": true,
      "expressions": [{
        "type": "erc20_transfer_matcher",
        "expression": {
          "address": "0xtoken_address",
          "log_name": "Transfer",
          "balances": "balances"
        }
      }],
      "delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
    }'

    # Alert 2: large transfers
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Large Transfers",
      "description": "Transfers of 1000+ tokens",
      "enabled": true,
      "expressions": [{
        "type": "emitted_log",
        "expression": {
          "address": "0xtoken_address",
          "event_name": "Transfer",
          "event_id": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
          "parameter_conditions": [
            {
              "parameter_name": "value",
              "parameter_type": "uint",
              "operator": ">=",
              "comparison_value": "1000000000000000000000"
            }
          ]
        }
      }],
      "delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
    }'

    # Alert 3: total supply changes
    curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
    --header "Content-Type: application/json" \
    --header "X-Access-Key: ${TENDERLY_API_KEY}" \
    --data-raw '{
      "name": "Supply Change",
      "description": "totalSupply moved by 1% or more",
      "enabled": true,
      "expressions": [{
        "type": "state_change",
        "expression": {
          "address": "0xtoken_address",
          "parameter_conditions": [
            {
              "parameter_name": "totalSupply",
              "parameter_type": "uint",
              "compare_percentage": true,
              "comparison_value": "1",
              "operator": ">="
            }
          ]
        }
      }],
      "delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
    }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    token_alerts = [
        # Alert 1: Transfer event consistency
        {
            "name": "Transfer Consistency",
            "description": "Transfer events inconsistent with balance changes",
            "enabled": True,
            "expressions": [{
                "type": "erc20_transfer_matcher",
                "expression": {
                    "address": "0xtoken_address",
                    "log_name": "Transfer",
                    "balances": "balances"
                }
            }],
            "delivery_channels": [{"id": "your_channel_id", "enabled": True}]
        },
        # Alert 2: large transfers
        {
            "name": "Large Transfers",
            "description": "Transfers of 1000+ tokens",
            "enabled": True,
            "expressions": [{
                "type": "emitted_log",
                "expression": {
                    "address": "0xtoken_address",
                    "event_name": "Transfer",
                    "event_id": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
                    "parameter_conditions": [
                        {
                            "parameter_name": "value",
                            "parameter_type": "uint",
                            "operator": ">=",
                            "comparison_value": "1000000000000000000000"
                        }
                    ]
                }
            }],
            "delivery_channels": [{"id": "your_channel_id", "enabled": True}]
        },
        # Alert 3: total supply changes
        {
            "name": "Supply Change",
            "description": "totalSupply moved by 1% or more",
            "enabled": True,
            "expressions": [{
                "type": "state_change",
                "expression": {
                    "address": "0xtoken_address",
                    "parameter_conditions": [
                        {
                            "parameter_name": "totalSupply",
                            "parameter_type": "uint",
                            "compare_percentage": True,
                            "comparison_value": "1",
                            "operator": ">="
                        }
                    ]
                }
            }],
            "delivery_channels": [{"id": "your_channel_id", "enabled": True}]
        }
    ]

    for alert in token_alerts:
        response = requests.post(
            f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
            headers=headers,
            json=alert
        )
    ```
  </Tab>
</Tabs>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.