---
title: "Needs attention"
description: "Rumoro checks every hour for spikes, negative turns, noisy keywords and failing channels, and tells you where you want."
canonical: https://docs.rumoro.dev/guides/attention
markdown: https://docs.rumoro.dev/guides/attention.mdx
---

# Needs attention

Rumoro checks every hour for spikes, negative turns, noisy keywords and failing channels, and tells you where you want.

Some things can't wait for tomorrow's digest. A keyword suddenly gets many times its usual mentions, a day turns negative, a keyword's matches are mostly noise that you still pay for, or a channel stops receiving. Rumoro looks for these every hour and opens an **attention item** for each one.

```ts tab="TypeScript"
const { data: items } = await rumoro.listAttention();
```

```python tab="Python"
items = rumoro.attention.list()
```

```bash tab="curl"
curl https://api.rumoro.dev/v1/attention \
  -H "Authorization: Bearer $RUMORO_API_KEY"
```

```json
{
  "data": [
    {
      "id": "att_...",
      "kind": "mention.spike",
      "status": "open",
      "subject": { "type": "keyword", "id": "kw_..." },
      "title": "Spike on driftwood: 23 mentions in an hour, usually about 3",
      "openedAt": "2026-10-04T15:00:00.000Z",
      "resolvedAt": null,
      "dismissedAt": null,
      "data": {
        "attentionId": "att_...",
        "url": "https://app.rumoro.dev/w/{workspaceId}/mentions?keywordId=kw_...",
        "keyword": { "id": "kw_...", "term": "driftwood", "kind": "brand", "name": "driftwood", "groupId": "grp_..." },
        "window": { "from": "2026-10-04T14:00:00.000Z", "to": "2026-10-04T15:00:00.000Z" },
        "matches": 23,
        "relevant": 17,
        "baseline": { "meanPerHour": 2.6, "stddevPerHour": 3.1, "hours": 168 }
      }
    }
  ],
  "nextCursor": null
}
```

By default you get open items. Set `status` to `resolved`, `dismissed` or `all` for older ones, and `kind` (comma-separated) to narrow the list. A page has 50 items (`limit` up to 100), newest first. Send `nextCursor` back as `cursor` for the next page. `openedAt` is the hour the item was found, the same as `window.to`.

## The four kinds

Rumoro checks once every UTC hour, starting two minutes past, and looks at the hour before.

| Kind | Opens when | Closes when |
| --- | --- | --- |
| `mention.spike` | A keyword's last full hour has at least 10 matches, at least 4 times its hourly average, and at least 4 standard deviations above it. Only posts published within 6 hours before they matched count, so look-backs and slow indexing don't trigger it. The average covers up to the previous week, and a keyword needs 3 days of data first. | The next hour is normal again |
| `sentiment.negative_spike` | In the last 24 hours, at least 5 of at least 10 relevant mentions are negative. That has to be 20% or more, and at least 2.5 times the keyword's usual share. The usual share comes from the week before and is smoothed for small keywords as (negative + 0.8) / (relevant + 10). | The last 24 hours no longer meet this |
| `keyword.noisy` | Its [health](/guides/keyword-health) is `noisy`, meaning 20 or more scored matches in 14 days (or since your last change) with less than 30% relevant | Health shows anything else, or the keyword is muted or deleted |
| `channel.failing` | A channel's last 5 deliveries in 24 hours all failed. Email limits, unconfirmed addresses and channel types that aren't set up on this deployment don't count as failures. | The channel delivers again, or is turned off or deleted |

## One item per episode

An item opens when its condition starts and closes by itself when the condition ends, so a spike that lasts three hours is one item. Each subject has at most one open item per kind, and after an item closes, the same kind doesn't open again for 24 hours. Closed items are listed with `status=resolved`.

```ts tab="TypeScript"
await rumoro.dismissAttention({ path: { id: 'att_...' } });
```

```python tab="Python"
rumoro.attention.dismiss("att_...")
```

```bash tab="curl"
curl -X POST https://api.rumoro.dev/v1/attention/att_.../dismiss \
  -H "Authorization: Bearer $RUMORO_API_KEY"
```

Dismissing hides an item for as long as its condition lasts. If the condition ends and starts again later, a new item opens.

## Getting notified

When an item opens, Rumoro also sends it once as an [account event](/webhooks/account-events) with the same name.

- **Webhooks** subscribe with `events` on the channel and receive the item's `data`.
- **Slack, email and Telegram** get a short "Needs attention" message with the title and an **Open in Rumoro** link. Turn on **Attention alerts** for a channel under Alerts, or send this.

```ts tab="TypeScript"
await rumoro.updateChannel({
  path: { id: 'dest_...' },
  body: { events: ['mention.spike', 'sentiment.negative_spike', 'keyword.noisy', 'channel.failing'] },
});
```

```python tab="Python"
rumoro.channels.update("dest_...", events=["mention.spike", "sentiment.negative_spike", "keyword.noisy", "channel.failing"])
```

```bash tab="curl"
curl -X PATCH https://api.rumoro.dev/v1/channels/dest_... \
  -H "Authorization: Bearer $RUMORO_API_KEY" -H "Content-Type: application/json" \
  -d '{ "events": ["mention.spike", "sentiment.negative_spike", "keyword.noisy", "channel.failing"] }'
```

Email follows the same rules as instant alerts, so only confirmed addresses, and at most 20 an hour per channel. When an item closes, nothing is sent.

The dashboard lists open items above the mentions under **Needs attention**, each with a **Dismiss** button. MCP has `list_attention` and `dismiss_attention`. The CLI has `attention:list` and `attention:dismiss`. Attention items cost nothing.
