The File System Watchers API lets you create and manage file system watchers that monitor paths for changes and stream events in real time via Server-Sent Events (SSE) or WebSocket connections. Use these endpoints to configure watchers, retrieve event history, and subscribe to live event streams.
Health
Section titled “Health”GET /api/v1/watch/health
Section titled “GET /api/v1/watch/health”Check the health status of the watch service.
This endpoint takes no parameters.
curl https://api.hoody.com/api/v1/watch/healthconst health = await client.watch.health.check();Service is healthy.
{ "status": "ok", "service": "watch", "started": "2026-02-11T08:00:00Z", "pid": 12345, "ip": "10.0.0.1", "built": "2026-02-10T12:00:00Z", "fds": 128, "memory": { "rss": 52428800, "heap": 31457280 }, "userAgent": "hoody-sdk/1.0"}Watchers
Section titled “Watchers”GET /watchers
Section titled “GET /watchers”List all configured file system watchers with pagination.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | No | Page number (1-based). |
limit | query | integer | No | Items per page (1-200). |
curl "https://api.hoody.com/watchers?page=1&limit=20"const watchers = await client.watch.watchers.listIterator({ page: 1, limit: 20});Watcher list.
{ "items": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "created_at": "2026-02-11T08:00:00Z", "config": { "paths": ["/home/user/documents"], "recursive": true, "include": ["*.txt", "*.md"], "exclude": ["*.tmp"], "ignore_dirs": ["node_modules", ".git"], "kinds": ["created", "modified", "removed"], "coalesce_ms": 100, "history_size": 1000, "history_limit_bytes": 10485760 }, "stats": { "events_seen": 42, "events_broadcast": 38, "events_dropped": 0, "stream_errors": 0, "active_clients": 1 } } ], "page": 1, "limit": 20, "total": 1}Invalid pagination.
{ "code": "INVALID_PAGINATION", "message": "Limit must be between 1 and 200", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_REQUEST | Invalid request | Request payload failed validation | Check request fields and retry |
INVALID_PAGINATION | Invalid pagination | Page or limit is out of range | Use page ≥ 1 and limit between 1 and 200 |
POST /watchers
Section titled “POST /watchers”Create a new file system watcher.
The request body is defined by the watch_CreateWatcherRequest schema.
curl -X POST https://api.hoody.com/watchers \ -H "Content-Type: application/json" \ -d '{ "paths": ["/home/user/documents"], "recursive": true, "include": ["*.txt", "*.md"], "exclude": ["*.tmp"], "ignore_dirs": ["node_modules"], "kinds": ["created", "modified", "removed"], "coalesce_ms": 100, "history_size": 1000 }'const watcher = await client.watch.watchers.create({ paths: ["/home/user/documents"], recursive: true, include: ["*.txt", "*.md"], exclude: ["*.tmp"], ignore_dirs: ["node_modules"], kinds: ["created", "modified", "removed"], coalesce_ms: 100, history_size: 1000});Watcher created.
{ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "created_at": "2026-02-11T08:00:00Z", "config": { "paths": ["/home/user/documents"], "recursive": true, "include": ["*.txt", "*.md"], "exclude": ["*.tmp"], "ignore_dirs": ["node_modules"], "kinds": ["created", "modified", "removed"], "coalesce_ms": 100, "history_size": 1000, "history_limit_bytes": 10485760 }, "stats": { "events_seen": 0, "events_broadcast": 0, "events_dropped": 0, "stream_errors": 0, "active_clients": 0 }}Invalid request.
{ "code": "INVALID_REQUEST", "message": "path list cannot be empty", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_REQUEST | Invalid request | Request payload failed validation | Check request fields and retry |
INVALID_PAGINATION | Invalid pagination | Page or limit is out of range | Use page ≥ 1 and limit between 1 and 200 |
Watcher or path limits exceeded.
{ "code": "LIMIT_EXCEEDED", "message": "watcher limit reached", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
LIMIT_EXCEEDED | Resource limit exceeded | Watcher or path limits exceeded | Reduce paths or delete unused watchers |
HISTORY_GAP | Replay history gap | Requested since_id is older than retained replay history | Reconnect without since_id or increase history_memory_limit_bytes |
Internal server error.
{ "code": "WATCHER_START_FAILED", "message": "failed to start watcher: inotify watch limit reached", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
WATCHER_START_FAILED | Watcher startup failed | Backend failed to initialize file watcher | Check path permissions and kernel watch limits |
GET /watchers/{id}
Section titled “GET /watchers/{id}”Get details for a specific watcher.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Watcher id |
curl https://api.hoody.com/watchers/a1b2c3d4-e5f6-7890-abcd-ef1234567890const watcher = await client.watch.watchers.get({ id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"});Watcher details.
{ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "created_at": "2026-02-11T08:00:00Z", "config": { "paths": ["/home/user/documents"], "recursive": true, "include": ["*.txt", "*.md"], "exclude": ["*.tmp"], "ignore_dirs": ["node_modules", ".git"], "kinds": ["created", "modified", "removed"], "coalesce_ms": 100, "history_size": 1000, "history_limit_bytes": 10485760 }, "stats": { "events_seen": 42, "events_broadcast": 38, "events_dropped": 0, "stream_errors": 0, "active_clients": 1 }}Watcher not found.
{ "code": "WATCHER_NOT_FOUND", "message": "Watcher not found", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
WATCHER_NOT_FOUND | Watcher not found | No watcher exists for provided id | List watchers and use a valid watcher id |
DELETE /watchers/{id}
Section titled “DELETE /watchers/{id}”Delete a file system watcher and stop all associated streams.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Watcher id |
curl -X DELETE https://api.hoody.com/watchers/a1b2c3d4-e5f6-7890-abcd-ef1234567890await client.watch.watchers.delete({ id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"});Watcher deleted.
{ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "deleted": true}Watcher not found.
{ "code": "WATCHER_NOT_FOUND", "message": "Watcher not found", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
WATCHER_NOT_FOUND | Watcher not found | No watcher exists for provided id | List watchers and use a valid watcher id |
Event Streaming
Section titled “Event Streaming”GET /watchers/{id}/events
Section titled “GET /watchers/{id}/events”Retrieve paginated event history for a watcher. Use since_id or since_timestamp to replay events from a specific point.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Watcher id |
since_id | query | integer | No | Replay events strictly after this event id. |
since_timestamp | query | string | No | Replay events strictly after this timestamp. Accepted formats: RFC3339 (e.g. 2026-02-11T15:30:00Z), Unix seconds (e.g. 1739287800), Unix milliseconds (e.g. 1739287800123). |
page | query | integer | No | Page number (1-based). |
limit | query | integer | No | Items per page (1-200). |
curl "https://api.hoody.com/watchers/a1b2c3d4-e5f6-7890-abcd-ef1234567890/events?page=1&limit=50"const events = await client.watch.streams.listEventsIterator({ id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", page: 1, limit: 50});Watcher event history.
{ "items": [ { "id": 1739287800001, "watcher_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "kind": "modified", "path": "/home/user/documents/notes.txt", "timestamp": "2026-02-11T15:30:00Z", "is_dir": false, "new_size_bytes": 2048, "old_size_bytes": 1024, "old_path": null, "details": null } ], "page": 1, "limit": 50, "total": 1, "newest_available_id": 1739287800001, "newest_available_timestamp": "2026-02-11T15:30:00Z", "oldest_available_id": 1739287800001, "oldest_available_timestamp": "2026-02-11T15:30:00Z"}Invalid query.
{ "code": "INVALID_PAGINATION", "message": "Limit must be between 1 and 200", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_REQUEST | Invalid request | Request payload failed validation | Check request fields and retry |
INVALID_PAGINATION | Invalid pagination | Page or limit is out of range | Use page ≥ 1 and limit between 1 and 200 |
Watcher not found.
{ "code": "WATCHER_NOT_FOUND", "message": "Watcher not found", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
WATCHER_NOT_FOUND | Watcher not found | No watcher exists for provided id | List watchers and use a valid watcher id |
Replay history gap.
{ "code": "HISTORY_GAP", "message": "Requested since_id is older than available replay history", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
LIMIT_EXCEEDED | Resource limit exceeded | Watcher or path limits exceeded | Reduce paths or delete unused watchers |
HISTORY_GAP | Replay history gap | Requested since_id is older than retained replay history | Reconnect without since_id or increase history_memory_limit_bytes |
GET /watchers/{id}/events/sse
Section titled “GET /watchers/{id}/events/sse”Stream watcher events in real time via Server-Sent Events (SSE). The connection remains open and emits events as they occur. Use since_id or since_timestamp to replay missed events before live streaming begins.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Watcher id |
since_id | query | integer | No | Replay events strictly after this event id. |
since_timestamp | query | string | No | Replay events strictly after this timestamp. Accepted formats: RFC3339 (e.g. 2026-02-11T15:30:00Z), Unix seconds (e.g. 1739287800), Unix milliseconds (e.g. 1739287800123). |
curl -N "https://api.hoody.com/watchers/a1b2c3d4-e5f6-7890-abcd-ef1234567890/events/sse?since_id=1739287800000"const stream = await client.watch.streams.streamSse({ id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", since_id: 1739287800000});SSE stream established. The connection remains open and emits events as they occur.
Watcher not found.
{ "code": "WATCHER_NOT_FOUND", "message": "Watcher not found", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
WATCHER_NOT_FOUND | Watcher not found | No watcher exists for provided id | List watchers and use a valid watcher id |
Replay history gap.
{ "code": "HISTORY_GAP", "message": "Requested since_id is older than available replay history", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
LIMIT_EXCEEDED | Resource limit exceeded | Watcher or path limits exceeded | Reduce paths or delete unused watchers |
HISTORY_GAP | Replay history gap | Requested since_id is older than retained replay history | Reconnect without since_id or increase history_memory_limit_bytes |
Too many stream clients.
{ "code": "MAX_CLIENTS_REACHED", "message": "Watcher has reached max stream clients", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MAX_CLIENTS_REACHED | Too many clients | Watcher stream client limit reached | Disconnect idle clients or increase max_clients_per_watcher |
GET /watchers/{id}/events/ws
Section titled “GET /watchers/{id}/events/ws”Stream watcher events in real time via WebSocket. The connection is upgraded to a WebSocket and remains open, emitting events as they occur. Use since_id or since_timestamp to replay missed events before live streaming begins.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Watcher id |
since_id | query | integer | No | Replay events strictly after this event id. |
since_timestamp | query | string | No | Replay events strictly after this timestamp. Accepted formats: RFC3339 (e.g. 2026-02-11T15:30:00Z), Unix seconds (e.g. 1739287800), Unix milliseconds (e.g. 1739287800123). |
curl -N \ -H "Connection: Upgrade" \ -H "Upgrade: websocket" \ "https://api.hoody.com/watchers/a1b2c3d4-e5f6-7890-abcd-ef1234567890/events/ws?since_id=1739287800000"const stream = await client.watch.streams.streamWs({ id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", since_id: 1739287800000});WebSocket connection upgraded. The connection remains open and emits events as they occur.
Watcher not found.
{ "code": "WATCHER_NOT_FOUND", "message": "Watcher not found", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
WATCHER_NOT_FOUND | Watcher not found | No watcher exists for provided id | List watchers and use a valid watcher id |
Replay history gap.
{ "code": "HISTORY_GAP", "message": "Requested since_id is older than available replay history", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
LIMIT_EXCEEDED | Resource limit exceeded | Watcher or path limits exceeded | Reduce paths or delete unused watchers |
HISTORY_GAP | Replay history gap | Requested since_id is older than retained replay history | Reconnect without since_id or increase history_memory_limit_bytes |
Too many stream clients.
{ "code": "MAX_CLIENTS_REACHED", "message": "Watcher has reached max stream clients", "details": null}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MAX_CLIENTS_REACHED | Too many clients | Watcher stream client limit reached | Disconnect idle clients or increase max_clients_per_watcher |