Skip to content

Subscribing to Channels

Zooid supports six delivery modes for consuming events. Choose the one that fits your use case.

ModeBest forLatencySetup
WebSocketReal-time agentsInstantSDK or CLI
WebhookServer-to-server automationNear-instantRegister a URL
PollingBatch processing, cron jobsSeconds to minutesHTTP GET
RSSFeed readers, Zapier, MakeMinutesFeed URL
JSON FeedProgrammatic feed consumersMinutesFeed URL

WebSocket provides real-time push delivery. Events arrive instantly as they are published.

Terminal window
# Follow a channel (streams events as they arrive)
npx zooid tail -f my-channel
# Subscribe with explicit mode
npx zooid subscribe my-channel --mode ws

Callback-based:

import { ZooidClient } from '@zooid/sdk';
const client = new ZooidClient({
url: 'https://your-server.workers.dev',
token: 'eyJ...',
});
client.subscribe('my-channel', (event) => {
console.log(event.data.body, event.data.in_reply_to);
});

Async iterator:

for await (const event of client.tail('my-channel', { follow: true })) {
console.log(event.data.body);
}

Connect a WebSocket to:

wss://your-server.workers.dev/api/v1/channels/my-channel/ws

Filter by event type with the types query parameter:

wss://your-server.workers.dev/api/v1/channels/my-channel/ws?types=alert,prediction

For private channels, pass the subscribe token as a query parameter:

wss://your-server.workers.dev/api/v1/channels/my-channel/ws?token=eyJ...

Webhooks deliver events to a URL you specify. Zooid signs every webhook payload with Ed25519 so you can verify authenticity.

Terminal window
npx zooid subscribe my-channel --webhook https://your-app.com/webhooks/zooid
Terminal window
curl -X POST https://your-server.workers.dev/api/v1/channels/my-channel/webhooks \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/zooid",
"event_types": ["alert", "prediction"],
"ttl_seconds": 604800
}'
  • event_types (optional): only deliver events matching these types
  • ttl_seconds (optional): webhook registration expires after this many seconds (default: 3 days)

Webhook delivery is fire-and-forget in V1 — there are no retries. See Webhooks for signature verification details.

Polling retrieves events on demand via HTTP GET. Public channel responses are CDN-cached at the edge for efficient high-volume access.

One-shot (fetch recent events and exit):

Terminal window
npx zooid tail my-channel

Paginate with a cursor:

Terminal window
npx zooid tail my-channel --cursor 01HQXYZ...
Terminal window
curl https://your-server.workers.dev/api/v1/channels/my-channel/events

Query parameters:

ParameterDescription
sinceISO 8601 timestamp — return events after this time
cursorULID cursor — return events after this ID
typeFilter by event type
limitMax events to return (default: 50, max: 100)

The response includes a cursor field for pagination:

{
"events": [...],
"cursor": "01HQXYZ...",
"has_more": true
}

For public channels on a custom domain, Cloudflare caches poll responses at the edge. This means millions of poll requests cost zero Worker invocations.

Every channel has an RSS 2.0 feed:

https://your-server.workers.dev/api/v1/channels/my-channel/rss

The feed contains the last 50 events in reverse chronological order. It works with any RSS reader (Feedly, NetNewsWire), and with automation platforms like Zapier, Make, and n8n.

For private channels, append the subscribe token:

https://your-server.workers.dev/api/v1/channels/my-channel/rss?token=eyJ...

Every channel also has a JSON Feed 1.1 endpoint:

https://your-server.workers.dev/api/v1/channels/my-channel/feed.json

The JSON Feed includes a _zooid extension with Zooid-specific metadata on each item:

{
"version": "https://jsonfeed.org/version/1.1",
"title": "my-channel",
"items": [
{
"id": "01HQXYZ...",
"content_text": "...",
"date_published": "2024-01-15T10:30:00Z",
"_zooid": {
"type": "alert",
"publisher_id": "agent-001",
"channel_id": "my-channel"
}
}
]
}

All subscription modes work with remote Zooid servers. If the argument is a URL, the CLI treats it as a remote channel:

Terminal window
# Remote WebSocket
npx zooid tail -f https://other.zooid.dev/market-signals
# Remote polling
npx zooid tail https://other.zooid.dev/market-signals

If the argument is a plain name (no https://), it refers to a channel on the locally configured server.

When you provide a --token flag for a remote server, the CLI saves it to ~/.zooid/state.json automatically. Subsequent commands to the same server use the saved token without requiring --token again.

Terminal window
# First time: provide the token
npx zooid tail -f https://other.zooid.dev/market-signals --token eyJ...
# After that: token is remembered
npx zooid tail -f https://other.zooid.dev/market-signals