# Cost Alerts

> List, create, change, pause and delete the cost alerts that watch an account, a saved cost view or your commitments, and read what each one has said.

Source: https://docs.levelfour.ai/resources/cost-alerts


The cost alert methods manage the rules [Cost alerts](/cost-alerts) describes. Reads take any key. Creating, changing, pausing and deleting take a read-write key. The examples show the Go, Python and TypeScript SDKs and plain HTTP. Python and TypeScript carry these methods from 0.2.0, and Go from v0.2.0.

## Methods

| Method                                                    | Returns                                                   |
| --------------------------------------------------------- | --------------------------------------------------------- |
| [List alerts](#list-alerts)                               | Every alert, with the live state of what each one watches |
| [List sources](#list-sources)                             | What an alert can watch                                   |
| [Create an alert](#create-an-alert)                       | The stored alert                                          |
| [Read one alert](#read-one-alert)                         | One alert                                                 |
| [Change an alert](#change-an-alert)                       | The alert as it now reads                                 |
| [Pause and resume](#pause-and-resume)                     | The alert, with who paused it                             |
| [Delete an alert](#delete-an-alert)                       | The id of the alert that is gone                          |
| [Alert events](#alert-events)                             | What one alert has said, newest first                     |
| [Suggestions for an account](#suggestions-for-an-account) | Rules the account's own billing history supports          |

## List alerts

Returns every alert in your organization. `watching` holds the live state of each thing an alert watches, as the last check left it: `ok`, `pending` or `firing`.

**Go**

```go  
alerts, err := client.CostAlerts.ListAlerts(ctx)
```

**Python**

```python  
alerts = client.cost_alerts.list_alerts()
```

**TypeScript**

```typescript  
const alerts = await client.costAlerts.listAlerts();
```

**HTTP**

```bash  
curl -s "https://api.levelfour.ai/api/v1/cost-alerts" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY"
```

## List sources

Returns every slice an alert can watch, as `id`, `label`, `group` and `provider`. `group` is `accounts`, `views` or `commitments`, and the `id` is what an alert's `source_id` takes.

**Go**

```go  
sources, err := client.CostAlerts.ListSources(ctx)
```

**Python**

```python  
sources = client.cost_alerts.list_sources()
```

**TypeScript**

```typescript  
const sources = await client.costAlerts.listSources();
```

**HTTP**

```bash  
curl -s "https://api.levelfour.ai/api/v1/cost-alerts/sources" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY"
```

## Create an alert

Creates an alert. `params` is the rule: `kind` is `budget`, `changes` or `commitment`, and [Cost alerts](/cost-alerts#types) says when each one fires. The example fires when month-to-date spend passes 80 percent of a 40,000 budget. An alert needs a member of your organization among its recipients, or a Slack channel.

**Go**

```go  
budget := func(amount float64) *levelfour.BudgetParamsInput {
    return &levelfour.BudgetParamsInput{
        Budget: &levelfour.BudgetParamsInputBudget{Double: amount},
        Reset:  "monthly",
        Rules: []*levelfour.BudgetRuleInput{
            {Amount: &levelfour.BudgetRuleInputAmount{Double: 80}, Unit: "percent"},
        },
    }
}

created, err := client.CostAlerts.CreateAlert(ctx, &levelfour.CreateAlertRequest{
    Name:       "Production budget",
    SourceID:   "123456789012",
    Params:     &levelfour.CreateAlertRequestParams{Budget: budget(40000)},
    Recipients: []*levelfour.AlertRecipient{{Name: "Ana", Email: "ana@example.com", Member: true}},
})
alertID := created.Data.ID
```

**Python**

```python  
from levelfour.cost_alerts import CreateAlertRequestParams_Budget
from levelfour.types import AlertRecipient, BudgetRuleInput

monthly = dict(reset="monthly", rules=[BudgetRuleInput(amount=80, unit="percent")])

created = client.cost_alerts.create_alert(
    name="Production budget",
    source_id="123456789012",
    params=CreateAlertRequestParams_Budget(budget=40000, **monthly),
    recipients=[AlertRecipient(name="Ana", email="ana@example.com", member=True)],
)
alert_id = created.data.id
```

**TypeScript**

```typescript  
const monthly = (budget: number) => ({
    kind: "budget" as const,
    budget,
    reset: "monthly" as const,
    rules: [{ amount: 80, unit: "percent" as const }],
});

const created = await client.costAlerts.createAlert({
    name: "Production budget",
    source_id: "123456789012",
    params: monthly(40000),
    recipients: [{ name: "Ana", email: "ana@example.com", member: true }],
});
const alert_id = created.data.id;
```

**HTTP**

```bash  
curl -s -X POST "https://api.levelfour.ai/api/v1/cost-alerts" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "Production budget",
    "source_id": "123456789012",
    "params": {"kind": "budget", "budget": 40000, "reset": "monthly", "rules": [{"amount": 80, "unit": "percent"}]},
    "recipients": [{"name": "Ana", "email": "ana@example.com", "member": true}]
  }'
```

Over HTTP, `slack_channel_ids` takes up to 10 Slack channel ids to post in. Left out, the alert posts in your organization's default channel, if one is set. The SDKs do not carry the field yet, so name channels over HTTP or in the dashboard.

## Read one alert

**Go**

```go  
alert, err := client.CostAlerts.GetAlert(ctx, alertID)
```

**Python**

```python  
alert = client.cost_alerts.get_alert(alert_id)
```

**TypeScript**

```typescript  
const alert = await client.costAlerts.getAlert({ alert_id });
```

**HTTP**

```bash  
curl -s "https://api.levelfour.ai/api/v1/cost-alerts/$ALERT_ID" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY"
```

## Change an alert

Only the fields you send change. `params` replaces the whole rule, so to move one threshold, send the rule back with that figure changed. The API refuses a field sent as `null`. This raises the budget to 50,000:

**Go**

```go  
_, err = client.CostAlerts.UpdateAlert(ctx, alertID, &levelfour.UpdateAlertRequest{
    Params: &levelfour.UpdateAlertRequestParams{Budget: budget(50000)},
})
```

**Python**

```python  
from levelfour.cost_alerts import UpdateAlertRequestParams_Budget

client.cost_alerts.update_alert(alert_id, params=UpdateAlertRequestParams_Budget(budget=50000, **monthly))
```

**TypeScript**

```typescript  
await client.costAlerts.updateAlert({ alert_id, params: monthly(50000) });
```

**HTTP**

```bash  
curl -s -X PATCH "https://api.levelfour.ai/api/v1/cost-alerts/$ALERT_ID" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"params": {"kind": "budget", "budget": 50000, "reset": "monthly", "rules": [{"amount": 80, "unit": "percent"}]}}'
```

## Pause and resume

Pausing is a change to `enabled`. `false` silences the alert and records who paused it in `paused_by`, and `true` arms it again. A paused alert keeps its history.

**Go**

```go  
enabled := false // true resumes it
_, err = client.CostAlerts.UpdateAlert(ctx, alertID, &levelfour.UpdateAlertRequest{Enabled: &enabled})
```

**Python**

```python  
client.cost_alerts.update_alert(alert_id, enabled=False)  # True resumes it
```

**TypeScript**

```typescript  
await client.costAlerts.updateAlert({ alert_id, enabled: false }); // true resumes it
```

**HTTP**

```bash  
curl -s -X PATCH "https://api.levelfour.ai/api/v1/cost-alerts/$ALERT_ID" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"enabled": false}'
```

## Delete an alert

Deletes the alert and every event it recorded. Nothing brings either back, so pause an alert you might want again.

**Go**

```go  
_, err = client.CostAlerts.DeleteAlert(ctx, alertID)
```

**Python**

```python  
client.cost_alerts.delete_alert(alert_id)
```

**TypeScript**

```typescript  
await client.costAlerts.deleteAlert({ alert_id });
```

**HTTP**

```bash  
curl -s -X DELETE "https://api.levelfour.ai/api/v1/cost-alerts/$ALERT_ID" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY"
```

## Alert events

Returns one entry per firing and per recovery, newest first, with the figure observed, the threshold it crossed and whether anyone was notified. `limit` is 1 to 200 and defaults to 50.

**Go**

```go  
events, err := client.CostAlerts.ListAlertEvents(ctx, alertID,
    &levelfour.ListAlertEventsAPIV1CostAlertsAlertIDEventsGetRequest{Limit: levelfour.Int(20)},
)
```

**Python**

```python  
events = client.cost_alerts.list_alert_events(alert_id, limit=20)
```

**TypeScript**

```typescript  
const events = await client.costAlerts.listAlertEvents({ alert_id, limit: 20 });
```

**HTTP**

```bash  
curl -s "https://api.levelfour.ai/api/v1/cost-alerts/$ALERT_ID/events?limit=20" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY"
```

## Suggestions for an account

Returns rules in the same grammar `params` takes, computed from the account's own billing history, with the baseline behind them. An account with too little history returns no suggestion rather than a number nobody can check.

**Go**

```go  
suggestions, err := client.CostAlerts.SuggestionsForAccount(ctx, "123456789012")
```

**Python**

```python  
suggestions = client.cost_alerts.suggestions_for_account("123456789012")
```

**TypeScript**

```typescript  
const suggestions = await client.costAlerts.suggestionsForAccount({ account_id: "123456789012" });
```

**HTTP**

```bash  
curl -s "https://api.levelfour.ai/api/v1/cost-alerts/suggestions/123456789012" \
  -H "Authorization: Bearer $LEVELFOUR_API_KEY"
```

## Related

* [Cost alerts](/cost-alerts): the types of rule, where alerts arrive, and how often they are checked
* [`l4 alerts`](/cli/commands/alerts): the same operations from the terminal
* [Cost Alerts API reference](/api-reference/cost-alerts): every field of every endpoint
