---
title: "Get a single alert delivery"
method: GET
path: "/v1/alerts/deliveries/{id}"
tags: ["Alerts", "tier:free"]
---

# Get a single alert delivery

`GET /v1/alerts/deliveries/{id}`

## Request

- Base URL: `https://api.particle.pro`
- URL: `https://api.particle.pro/v1/alerts/deliveries/{id}`
- Auth: none required

Returns one delivery with its embedded matches (paginated — see matches_cursor). The URL is keyed only by the delivery ID — the parent alert ID is intentionally omitted so a landing-page link can be shared publicly without leaking the alert identifier. Works for all cadences — immediate, daily, weekly digests. URL possession is the access factor; the endpoint is reachable without auth (the IDs are unguessable). Authenticated members of the delivery's owning organization receive the high-resolution payload (transcript Windows when `view=detailed`, mention variants, salience, delivery audit). For a member-viewed WEBHOOK delivery, has_webhook_payload is true and the exact POSTed JSON is available from GET /v1/alerts/deliveries/{id}/webhook-payload (not embedded here — it can be many MB). Unauthenticated and non-member callers receive a reduced public payload — alert title and kind, match entity and episode metadata, no internal fields.

## Path parameters

- `id` string, required: Delivery ID

## Query parameters

- `view` 'summary' | 'detailed': Hydration depth for the embedded matches. Both views include Episode metadata (episode title, podcast title, image) so the FE can render a card per match. 'summary' (default) omits transcript Windows; 'detailed' includes them — pick 'detailed' when rendering a full landing page where each match expands to the spoken excerpt, 'summary' for a list view.
- `matches_limit` integer: Max embedded matches to return in this response (default and max 100). The delivery's true total is always match_count; use matches_cursor to page through the rest.
- `matches_cursor` string: Opaque cursor from a previous response's matches_cursor, to fetch the next page of embedded matches.

## Response `200`

OK

- AlertDeliveryDetail
  - `alert` AlertRef
    - `id` string, required
    - `kind` 'ENTITY_MENTION' | 'PODCAST_SPEAKER' | 'KEYWORD_MENTION', required: Inherited from the parent alert's kind. See AlertMatch.kind.
    - `organization_id` string: Owning organization. Omitted for non-member callers.
    - `project_id` string: Owning project. Lets a deep-linked delivery select the right project in the dashboard. Omitted for non-member callers.
    - `title` string, required
  - `alert_id` string, required: ID of the parent alert.
  - `channel` string, required
  - `created_at` string, date-time, required
  - `error_message` string
  - `has_webhook_payload` boolean, required: Whether this delivery has a reconstructable webhook payload (member-viewed WEBHOOK deliveries only). When true, fetch the exact POSTed JSON from GET /v1/alerts/deliveries/{id}/webhook-payload — it is not embedded here because it can be many MB.
  - `id` string, required
  - `match_count` integer, required
  - `matches` AlertMatch[], nullable, required
    - `alert_id` string, required: ID of the parent alert.
    - `deliveries` AlertDeliverySummary[], nullable, required
      - `channel` string, required
      - `created_at` string, date-time, required
      - `error_message` string
      - `id` string, required
      - `sent_at` string, date-time
      - `status` string, required: Delivery outcome — SENT (delivered; a partial success keeps this status with the failure noted in error_message), FAILED (an attempt failed; realtime retries within its budget and digests re-select within their window), SKIPPED (intentionally not delivered), or ABANDONED (realtime webhook delivery permanently gave up after exhausting its retry budget, so the match was dropped for that channel).
    - `detected_at` string, date-time, required
    - `entity_id` string, required
    - `entity_type` string, required: Type of the watched target: PERSON, COMPANY, or KNOWLEDGE_GRAPH_ENTITY for entity alerts, KEYWORD for KEYWORD_MENTION alerts.
    - `episode` AlertMatchEpisode
      - `apple_podcasts_url` string: Apple Podcasts deep-link for the parent podcast. Omitted when the podcast has no iTunes ID.
      - `audio_url` string: CDN-fronted URL for the full episode audio, playable directly in a browser <audio> element without auth (the podcast's own public media). Clients play a specific window by loading this and seeking to the window's start_seconds. Omitted when the episode has no stored audio yet. Present on both the member and public landing-page tiers so a shared link can play the clip.
      - `duration_seconds` number, double: Total episode duration in seconds. Omitted when unknown.
      - `explicit` boolean: Whether the episode is flagged as containing explicit content by its publisher.
      - `image_url` string: Episode-specific image. Omitted when the episode has no dedicated image. Clients should fall back to podcast_image_url for a card thumbnail in that case.
      - `podcast_bias` 'EXTREME_LEFT' | 'LEANS_LEFT' | 'LEFT' | 'CENTER' | 'RIGHT' | 'LEANS_RIGHT' | 'EXTREME_RIGHT': Political bias rating for the parent podcast. Omitted when the podcast is not substantively political or has not been evaluated yet. Fetch GET /v1/podcasts/{id}/bias for the full analysis including reasoning and evidence.
      - `podcast_id` string, required
      - `podcast_image_url` string: Parent podcast's image. Suitable as a fallback when image_url is absent.
      - `podcast_popularity` number, double: Parent podcast's global popularity percentile in (0,1] — a cume_dist ranking over all currently-charting podcasts (Apple Podcasts charts). Higher is more popular; 1.0 is the most popular show. Omitted when the podcast is not currently charting.
      - `podcast_popularity_badge` 'Top Podcast' | 'Very Popular' | 'Popular': Human-facing reach tier derived from podcast_popularity: Top Podcast (top 1%), Very Popular (top 5%), or Popular (top 10%). Omitted for shows outside the top 10%.
      - `podcast_slug` string
      - `podcast_title` string, required
      - `published_at` string, date-time
      - `slug` string
      - `title` string, required
    - `id` string, required
    - `is_backfilled` boolean: True for matches written by the post-create historical sweep. Backfilled matches are real matches the live pipeline would have produced, with DetectedAt set to the source episode's publish time. They never trigger delivery (no email is sent) — the field lets the UI label them so users can distinguish 'past' from 'going-forward' matches.
    - `keyword` string: KEYWORD_MENTION matches only: the phrase this match fired on. It stays the phrase that matched even if the alert's keyword is later edited.
    - `kind` 'ENTITY_MENTION' | 'PODCAST_SPEAKER' | 'KEYWORD_MENTION', required: Inherited from the parent alert's kind so clients can render mention vs appearance semantics without a follow-up alert lookup. Match payloads from ENTITY_MENTION and KEYWORD_MENTION alerts carry mention_count and mention_variants; PODCAST_SPEAKER matches carry roles and a line-count in mention_count.
    - `llm_summary` string: AI-generated narrative summary of this match with prior-mention context from the past 7 days for the same (alert, entity). Generated asynchronously after match creation. Absent (field omitted) when the summarizer hasn't processed the row yet OR when the LLM exhausted its retry budget — clients should treat both states the same: no summary to render. Visible to both org members and the public landing-page tier; the summary describes the mention itself, not the alert configuration.
    - `mention_count` integer, required
    - `mention_variants` string[], nullable
    - `monitor_id` string, required: Deprecated — use alert_id. ID of the parent alert.
    - `relevance` 'on_target' | 'incidental': How this match relates to the watched entity, classified by the summarizer: on_target (the entity is the mention's subject or a substantive reference) or incidental (a correct but passing reference in service of another story). Absent when unjudged. Lets a client tell a substantive mention from a fly-by one. (A third internal verdict, wrong_entity, marks knowledge-graph name collisions; those matches are suppressed before delivery and never appear here.)
    - `roles` string[], nullable: Canonical speaker role(s) the matched entity appeared as, drawn from the alert's speaker roles: by default GUEST, PANELIST, CORRESPONDENT, AUDIENCE, or SOUNDBITE_SPEAKER (an excerpted clip of them, not a live appearance), and HOST only when speaker_roles includes it. Raw STT/LLM labels like CALLER, REPORTER, LISTENER are normalized to these buckets on write. Populated only for PODCAST_SPEAKER matches; sorted alphabetically for deterministic order.
    - `source_id` string, required
    - `source_type` string, required
    - `truncated` boolean
    - `windows` AlertMatchWindow[], nullable
      - `clip_description` string
      - `clip_id` string
      - `clip_intro_statement` string
      - `clip_title` string
      - `clip_type` string
      - `end_seconds` number, double, required
      - `lines` AlertMatchLine[], nullable, required
        - `end_seconds` number, double, required
        - `is_mention` boolean
        - `number` integer
        - `role` string
        - `speaker` string
        - `start_seconds` number, double, required
        - `text` string, required
      - `segment_description` string
      - `segment_id` string
      - `segment_summary` string
      - `segment_title` string
      - `segment_type` string
      - `start_seconds` number, double, required
  - `matches_cursor` string: Opaque cursor; pass as ?matches_cursor= to fetch the next page of matches. Absent when there are no more.
  - `matches_has_more` boolean, required: Whether more matches exist beyond this page. The true total is match_count.
  - `monitor` AlertRef
    - `id` string, required
    - `kind` 'ENTITY_MENTION' | 'PODCAST_SPEAKER' | 'KEYWORD_MENTION', required: Inherited from the parent alert's kind. See AlertMatch.kind.
    - `organization_id` string: Owning organization. Omitted for non-member callers.
    - `project_id` string: Owning project. Lets a deep-linked delivery select the right project in the dashboard. Omitted for non-member callers.
    - `title` string, required
  - `monitor_id` string, required: Deprecated — use alert_id. ID of the parent alert.
  - `sent_at` string, date-time
  - `status` string, required: Delivery outcome — SENT (delivered; a partial success keeps this status with the failure noted in error_message), FAILED (an attempt failed; realtime retries within its budget and digests re-select within their window), SKIPPED (intentionally not delivered), or ABANDONED (realtime webhook delivery permanently gave up after exhausting its retry budget, so the match was dropped for that channel).
  - `viewer_can_manage` boolean, required: Whether the caller is a member of the owning org (or an API key scoped to the owning project) and can manage this alert in-app. True responses carry the member-only fields; false responses are the public projection with those fields stripped. Clients must read this rather than inferring access from field presence.

## Other responses

- `default`: Error

---

[API](https://skmtc.dev/particle/apis/particle-api.md) · [All operations](https://skmtc.dev/particle/apis/particle-api/llms.txt) · [OpenAPI document](https://skmtc.dev/particle/apis/particle-api/revisions/416ba82ab9d7?raw)
