---
title: "Report stream (SSE)"
method: GET
path: "/check/stream"
tags: ["check"]
---

# Report stream (SSE)

`GET /check/stream`

The Server-Sent Events feed behind the report page: the same verdict data
as `/check`, delivered phase by phase as each is produced instead of after
the slowest upstream. **The only non-JSON success response in this API.**

**Authentication is optional.** An API key or session cookie is accepted
and trusted; an anonymous caller is rate-limited by IP (10/hour). Cache
replays are open to everyone. A **live** run — cold cache miss, or a
stale entry due for refresh — is started only for an authenticated caller
or an anonymous one presenting the `pt` token the report page minted;
without it, a cold miss answers 429 and a stale entry is served as-is with
no refresh. Automation user-agents are treated as untrusted. With an API
key this is metered like any `/check`-family request.

**Wire format.** Each event is one `data:` line carrying
`{"type": "<type>", "data": {…}}` followed by a blank line; there are no
`event:` or `id:` fields. A `: keep-alive` comment is sent after 15 s of
silence. The connection is closed at a 55 s deadline whatever has been
emitted.

**Event types**, in emission order: `reputation` (may be sent twice — a
fast verdict, then a corrected one), `basic`, `insights`, `enrichment`
(zero or more frames, one per enrichment facet, then a terminal frame
`{"enrichmentDone": true, "emitted": [<facet keys>]}`), `dns`, and `done`
(`{"timings": {…}}`, plus `"earlyExit": true` when the pipeline stopped
early). New types are additive; consumers must ignore unknown ones. The
per-event `data` shapes are owned by the consumer's type file
(`apps/web/lib/report-stream-types.ts`, `SSE_EVENT_KEYS`) and are not
modelled as a schema here.

## Query parameters

- `query` string
- `pt` string

## Response `200`

SSE stream — frame contract in the operation description

## Other responses

- `400` — `query` missing or blank: `{"error": "query parameter is required"}`
- `401` — A credential or session cookie was presented and is invalid. Requests with no credential at all are served anonymously, not refused
- `429` — Anonymous burst limit (10/hour per IP; `Retry-After` and `X-RateLimit-*` headers), or an anonymous live check without a `pt` token: `{"error": "Rate limit exceeded", "message": "Anonymous live checks require opening the report page."}`. Authenticated callers get their plan's burst/quota 429

## Changes

- **2026-09-02** `b834b2860af7` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api/changes/check/stream/get.md)

---

[API](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api.md) · [All operations](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/ismalicious/ismalicious-threat-intelligence-api/revisions/b834b2860af7/schema)
