Live click feed across the caller's own links (SSE)
EAS-83 follow-up: a workspace-scoped Server-Sent Events feed for surfaces that aren't pinned to one link (the Dashboard, Links List, Campaigns, and Analytics pages) — same underlying ~500ms click-batch pipeline as GET /v1/links/{id}/stream, just a second subscription mode over it. Emits `data: {"linkId": "...", "clicks": N, "campaignId": "...", "committedAt": "..."}` — a per-link count for that flush, not enriched per-click detail — as each affected link's batch is durably persisted, plus `: ping` heartbeat comments roughly every 25s. `campaignId` is omitted when the link has none, so a client can attribute a live click to its campaign (the Campaigns list/detail pages) without a second lookup. Scoped to exactly the links the caller owns in their active org (the same population GET /v1/analytics/summary reports on) — a teammate's org-shared link never contributes here, matching that endpoint's existing scope. Open streams are capped per workspace and per user on each replica; past a cap the response is 429 with a plain-language message and the client retries on its own. `committedAt` is when the batch was recorded, to compare with the `asOf` of a read. The server ends the stream when the caller's access token expires, so a client reconnects (refreshing its token) and refetches — clicks in the gap are not replayed. Every couple of minutes the server also re-checks that the caller still has access (their identity has not changed) and ends the stream if not.
View as MarkdownAuthorization
bearer In: header
Response Body
text/event-stream
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/links/stream""string"Export a link's clicks as CSV
Raw enriched click log for one link over the requested window as a CSV attachment (at, country, device, browser, os, referrerHost, referrer, isBot). Bot rows are included and flagged, unlike the in-app analytics which exclude them. Capped at 50000 rows; a trailing "truncated" row signals the cap.
Live click feed for one link (SSE)
EAS-83: a Server-Sent Events stream of new clicks on this link as they're recorded. Layered on top of the existing ~500ms click-batch pipeline (never a separate capture path): the connection emits `data: <Click>` for each click as its batch is durably persisted (bot clicks excluded, same as recentClicks), one JSON object per click, plus `: ping` heartbeat comments roughly every 25s. One-way and stateless — any replica can serve any client. Same readable scope as GET /v1/links/{id}: the owner, or anyone in the organization when the link's visibility is "org". EAS-83 follow-up: each Click also carries `clicksUsed`/`qrScansUsed` — the same live Redis usage-cap counts GET /v1/links/{id} returns at the top level — so a client can track the Click/QR-scan-limit stats live instead of only refreshing them on the next full reload. Both are omitted if the usage limiter isn't wired server-side (same best-effort degrade as GET's own clicksUsed/qrScansUsed). Open streams are capped per link and per user on each replica; past a cap the response is 429 with a plain-language message and the client retries on its own. The server ends the stream when the caller's access token expires, so a client reconnects (refreshing its token) and refetches — clicks in the gap are not replayed. Every couple of minutes the server also re-checks that the caller still has access (their identity has not changed, and the link still exists and is readable by them) and ends the stream if not.