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

# Alert results

> Read the matches an alert detects, the emails it sends, and the shareable pages behind every result.

An alert produces two kinds of record. A **match** is one detected mention or appearance of a watched entity on a single episode. A **delivery** records one send attempt — a single row covering all of the alert's recipients, who are each emailed individually. A realtime delivery carries a single match; a [daily or weekly digest](/alerts/overview#delivery-frequency) bundles every match in its window into one delivery.

## Matches

Each match links a watched entity to the episode it was found on, with the evidence that triggered it.

| Field                      | Description                                                                                                                                                                                                                                                                                                                         |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entity_type`, `entity_id` | The watched entity this match is for.                                                                                                                                                                                                                                                                                               |
| `source_type`, `source_id` | The source object. Currently always a podcast episode.                                                                                                                                                                                                                                                                              |
| `detected_at`              | When the match was produced. For backfilled matches this is the episode's publish time.                                                                                                                                                                                                                                             |
| `mention_count`            | Mentions in the episode (`ENTITY_MENTION`), or spoken lines by the entity (`PODCAST_SPEAKER`).                                                                                                                                                                                                                                      |
| `relevance`                | `on_target` (the entity is the subject of discussion) or `incidental` (a passing reference). Absent on matches the summarizer hasn't judged yet. An alert with `filters.relevance: "RELEVANT"` only surfaces `on_target` matches; with the default `EVERYTHING`, both are returned.                                                 |
| `mention_variants`         | The surface forms the entity was referred to by. `ENTITY_MENTION` only.                                                                                                                                                                                                                                                             |
| `roles`                    | Canonical speaker roles the entity appeared as — `GUEST`, `PANELIST`, `CORRESPONDENT`, or `AUDIENCE`. `PODCAST_SPEAKER` only.                                                                                                                                                                                                       |
| `windows`                  | Transcript excerpts: contiguous dialogue around each mention, with per-line speaker, timestamps, and an `is_mention` flag.                                                                                                                                                                                                          |
| `llm_summary`              | An AI-written summary of the match with context from the entity's mentions over the prior 7 days. Generated shortly after the match; absent until then, and permanently absent if generation fails after retries (treat a missing summary the same either way).                                                                     |
| `is_backfilled`            | `true` for matches found by the post-create historical sweep. These never sent an email.                                                                                                                                                                                                                                            |
| `episode`                  | Episode and podcast metadata (titles, image, slugs) so a result renders as a card without a second lookup. Present on the single-match and delivery-detail responses and on preview samples; **omitted from the paginated matches list** below — fetch a single match (or `GET /v1/podcasts/episodes/{id}`) when you need it there. |

### List matches

```bash theme={"dark"}
curl "https://api.particle.pro/v1/alerts/8Qw2mRk7Tf9LpZ/matches?limit=20" \
  -H "X-API-Key: $PARTICLE_API_KEY"
```

Results are newest-first and paginated with the standard [cursor envelope](/concepts#cursor-pagination). Narrow to a window with `after` and `before` — both **exclusive** bounds on `detected_at`. A bare date is parsed as midnight UTC, so to include a whole day set `before` to the next day (the call below captures all of June 1 through June 9):

```bash theme={"dark"}
curl --get "https://api.particle.pro/v1/alerts/8Qw2mRk7Tf9LpZ/matches" \
  --data-urlencode "after=2026-06-01" \
  --data-urlencode "before=2026-06-10" \
  -H "X-API-Key: $PARTICLE_API_KEY"
```

```json Response (truncated) theme={"dark"}
{
  "data": [
    {
      "id": "Mt7k…",
      "alert_id": "8Qw2mRk7Tf9LpZ",
      "kind": "ENTITY_MENTION",
      "entity_type": "COMPANY",
      "entity_id": "3CensCwu5G2oKCFgPrNf89",
      "source_type": "PODCAST_EPISODE",
      "source_id": "78cgekLUjCJBUZbj3s5K8Y",
      "detected_at": "2026-06-08T11:02:00Z",
      "mention_count": 4,
      "relevance": "on_target",
      "mention_variants": ["Nvidia", "NVDA"],
      "llm_summary": "Discussed Nvidia's data-center revenue in the context of …",
      "deliveries": [
        { "id": "Dl9…", "channel": "EMAIL", "status": "SENT", "sent_at": "2026-06-08T11:03:12Z" }
      ]
    }
  ],
  "has_more": true,
  "cursor": "…"
}
```

The match payload differs by alert kind. `ENTITY_MENTION` matches carry `mention_count`, `mention_variants`, and the mention `windows`. `PODCAST_SPEAKER` matches carry `roles` and report the entity's spoken-line count in `mention_count`. `windows` are present on both when the match is hydrated (the single-match and detailed delivery views below).

The matches list reflects the alert's [`filters`](/alerts/overview#filtering-matches): if you configured `languages`, `relevance`, `source_popularity`, or `speaker_roles`, this endpoint only returns matches that survive the *current* filter set — the same set the emails carry. Two consequences worth knowing:

* **`relevance` and `source_popularity` are applied at read time.** Tightening either filter hides matches that no longer satisfy it; loosening it brings them back. The underlying match rows are unchanged.
* **`languages` and `speaker_roles` are applied at detection AND backfill.** Tightening either filter hides existing matches the same way, but loosening one **does not** surface older matches that were excluded — those matches were never written, because the post-create historical sweep and the live matcher both gate on these axes before creating rows. Treat narrowing on these axes as a one-way trim of historical coverage.

## Backfill

When an alert is created, Particle sweeps the previous 7 days and writes any matches the live pipeline would have produced, so the alert isn't empty on day one. These are flagged `is_backfilled: true` with `detected_at` set to the episode's publish time, and they **never trigger an email** — only matches detected after creation are delivered.

## Deliveries

The deliveries log is the email audit trail for an alert — one row per send attempt.

```bash theme={"dark"}
curl "https://api.particle.pro/v1/alerts/8Qw2mRk7Tf9LpZ/deliveries?limit=20" \
  -H "X-API-Key: $PARTICLE_API_KEY"
```

```json Response (truncated) theme={"dark"}
{
  "data": [
    {
      "id": "Dl9…",
      "alert_id": "8Qw2mRk7Tf9LpZ",
      "channel": "EMAIL",
      "status": "SENT",
      "sent_at": "2026-06-08T11:03:12Z",
      "match_count": 1,
      "created_at": "2026-06-08T11:03:10Z",
      "matches": [
        { "id": "Mt7k…", "entity_type": "COMPANY", "detected_at": "2026-06-08T11:02:00Z" }
      ]
    }
  ],
  "has_more": false
}
```

`status` is one of `SENT`, `FAILED`, or `SKIPPED`, and `error_message` carries the detail for anything that isn't a clean success — so check it even when `status` is `SENT`:

* **`SENT`** — the email was sent. If some recipients failed on a digest, the status stays `SENT` (so those who got it aren't re-emailed) and `error_message` records the partial failure, e.g. `2/5 recipients failed`.
* **`FAILED`** — no recipient received the email; `error_message` has the reason, and the send is retried.
* **`SKIPPED`** — no email was attempted (for example, the alert has no email recipients); `error_message` explains why.

A realtime delivery has `match_count: 1`; a daily or weekly digest groups its whole window into one delivery with a higher `match_count`. Each delivery embeds a lightweight summary of the matches it included — for the full transcript excerpts, fetch the delivery's shareable page or the individual matches.

## Shareable result pages

Two API endpoints return a single result on its own — fetch one delivery or match by ID, without the parent alert:

* `GET /v1/alerts/deliveries/{id}` — one delivery and the matches it contained
* `GET /v1/alerts/matches/{id}` — one match, fully hydrated

These JSON endpoints (on `api.particle.pro`) also back the human-readable landing pages the platform renders for the **View in browser** and per-result links in alert emails — those email links point at `platform.particle.pro`, not the API.

```bash theme={"dark"}
# A delivery landing page, with full transcript excerpts
curl "https://api.particle.pro/v1/alerts/deliveries/Dl9XYZ?view=detailed" \
  -H "X-API-Key: $PARTICLE_API_KEY"
```

Both are keyed only by the resource's own ID — the parent alert ID is deliberately absent from the URL so a link can be shared without revealing which alert it came from. **Possession of the link grants read access**; the IDs are unguessable. The response fidelity then depends on who's asking:

* **The alert's owners** get the full payload: transcript `windows`, mention variants, and speaker roles. An **API key qualifies only if it's scoped to the alert's project** — a key from another project, even in the same organization, gets the reduced payload; a **signed-in user** qualifies if they're a member of the alert's organization. On the single-match endpoint (`GET /v1/alerts/matches/{id}`) owners also get the match's `deliveries` array — the per-channel send audit — which is stripped for everyone else.
* **Everyone else** gets a reduced public payload — the entity, the episode metadata, `detected_at`, `mention_count`, and the AI summary — enough to render a result card, with the internal scoring and configuration stripped.

On the delivery endpoint, `view` controls excerpt depth for members: `summary` (default) omits transcript `windows`; `detailed` includes them. Use `detailed` to render a full results page where each match expands to the spoken excerpt.

## Stop delivery

Two ways to stop an alert:

* **Pause it** — `PATCH /v1/alerts/{id}` with `is_active: false`. The alert keeps its history and can be resumed. See [Update, pause, and delete](/alerts/create#update-pause-and-delete).
* **One-click disable from an email** — every alert email has a **Disable this alert** link in its footer carrying a single-use token. Opening it shows the alert it controls; confirming flips `is_active` to `false`. The recipient doesn't need a Particle account — token possession is the access factor. Replaying an already-used link is harmless: it returns the alert's current `is_active` state with an `already_disabled` flag, so an alert that was re-enabled after the first click correctly shows as active again.

## Related

* [Alerts overview](/alerts/overview) — concepts, alert kinds, and the plan requirement
* [Create and manage alerts](/alerts/create) — resolve an entity, preview, create, update
* [Transcripts → Mentions](/podcasts/transcripts#transcript-mentions) — the dialogue-window shape that match excerpts mirror
