# Connect to anonymous site-wide presence

Same-origin WebSocket only. Send SitePresenceReportV1 text frames (maximum 512 characters) at most five times per second with a 25-second heartbeat. A tab-scoped UUID session produces a hashed public ID that survives navigation; the session is never broadcast. Snapshots follow SitePresenceSnapshotV1. No URLs, content, playback, names, or free text are accepted. Maximum 200 connections; reports expire after 75 seconds and are swept every 30 seconds. This ephemeral coordination channel is independent of the radio room and canonical content.

Operation: joinSitePresence
GET /api/site/presence

Access: anonymous. Automatic retries: none. Redirects: manual. Request body limit: 0 bytes.
Default timeout: 30 seconds. Response limit: 16 MiB. Pagination is opt-in and bounded; an exhausted bound reports incomplete execution.

[HTML reference](/developers/api/joinSitePresence) · [Authoritative schemas](/api/openapi.json)

## Wire contract

```json
{
  "operationId": "joinSitePresence",
  "summary": "Connect to anonymous site-wide presence",
  "tags": [
    "site"
  ],
  "description": "Same-origin WebSocket only. Send SitePresenceReportV1 text frames (maximum 512 characters) at most five times per second with a 25-second heartbeat. A tab-scoped UUID session produces a hashed public ID that survives navigation; the session is never broadcast. Snapshots follow SitePresenceSnapshotV1. No URLs, content, playback, names, or free text are accepted. Maximum 200 connections; reports expire after 75 seconds and are swept every 30 seconds. This ephemeral coordination channel is independent of the radio room and canonical content.",
  "responses": {
    "101": {
      "description": "WebSocket connected; send initial presence frame"
    },
    "403": {
      "description": "Origin rejected"
    },
    "405": {
      "description": "GET required"
    },
    "426": {
      "description": "WebSocket required"
    },
    "429": {
      "description": "Admission limited; Retry-After: 60"
    },
    "503": {
      "description": "Presence unavailable or full"
    }
  }
}
```

## Synthetic examples

### curl

```bash
curl --fail-with-body --max-time 30 --max-filesize 16777216 --request GET 'https://irvinebroque.com/api/site/presence'
```

### TypeScript

```typescript
import { PublicApi } from '@irvinebroque/public-api';
const api = new PublicApi();
const result = await api.site.presenceProbe({});
console.log(result.status, result.headers.get('content-type')); // Keep transient capabilities in memory.
```

### CLI

```bash
irvinebroque site presence-probe
```
