---
title: "Stream Certificates"
method: GET
path: "/v1/stream"
tags: ["stream"]
---

# Stream Certificates

`GET /v1/stream`

## Request

- Base URL: `https://api.ctindex.io`
- URL: `https://api.ctindex.io/v1/stream`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Subscribe to the real-time CT firehose as Server-Sent Events.

The response body is an infinite SSE stream. Each newly-indexed cert is
delivered as::

    event: certificate
    id: <replay-buffer event id>
    data: {"sha256": "...", "subject_cn": "...", "sans": [...], ...}

Non-certificate events use their own event name — currently
``event: backfill_complete`` (fired when an on-demand cold-domain
backfill finishes; the JSON body carries ``domain``, ``status``,
``cert_count`` and timing fields). The ``?domain=`` filter applies to
these too, matched against the event's ``domain``.

**Resume semantics** (replay buffer): every event carries an ``id:``.
Reconnect with the standard ``Last-Event-ID`` header (or a
``?last_event_id=`` query param, for EventSource clients that cannot
set headers) to resume in-order, without duplicates, from the event
after that id. The replay buffer is bounded two ways: a time bound
(``firehose_replay_retention_hours``, default 72h) and an entry-count
memory cap (``firehose_replay_maxlen``, default 100k) — the effective
horizon is whichever is smaller for the current event volume. If your
``Last-Event-ID`` has aged out of the buffer, the stream sends one
explicit ``event: gap`` (``replay_horizon_exceeded``) and then resumes
from the oldest retained event; reconcile the missed window via the
search API. A malformed ``Last-Event-ID`` degrades to live-only
delivery (never a 4xx).

**Stall detection**: during quiet periods the server emits a
``: keep-alive`` comment every ``firehose_keepalive_seconds`` (default
15s). A client that has received no bytes at all for more than ~2x
that cadence should assume the connection is dead, drop it, and
reconnect with its last seen ``Last-Event-ID`` — the replay buffer
makes that reconnect lossless within the retention horizon.

The stream stays open until the client disconnects or the server is
shut down. ``Retry-After`` semantics are deliberately not used — SSE
clients reconnect on their own.

## Query parameters

- `domain` string, nullable: Optional domain filter (case-insensitive). Matches subject CN and SANs; understands wildcard SANs like *.example.com.
- `token` string, nullable: Short-lived stream token from POST /v1/stream/token, or a raw API key (legacy). The header is preferred for server-to-server clients; the token query param is for browsers (EventSource has no header support).

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

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