Installation
Quick start
Configuration
The client accepts nothing (free tier, orBOROUGH_API_KEY from the environment), a string (API key), or a config object:
Resources
The client exposes resource modules following a consistent pattern:listings.stream(), watchers, and webhooks. See Streams and watchers below and Webhook verification.
Detail methods (listings.get, listings.getByUrl, buildings.get) report how the data was served in meta.source: cached, stale, or live. On Business, stale detail is fetched live before responding, and paid tiers queue a background refresh for stale data. Live fetches and refreshes draw on a shared live-fetch budget. When that budget is held for Borough’s scheduled updates, or live fetching is paused, these methods return cached data (source: "cached" or "stale") instead of live.
Streams and watchers
Listing stream (Pro+)
listings.stream(id) opens a server-sent event stream: a cached event with the stored record, then a live event with freshly fetched data, then done. The live fetch uses the same shared live-fetch budget. When that budget is held for scheduled updates or live fetching is paused, the stream sends an error event with code budget_exceeded or service_disabled in place of live, and the cached event stands.
Watchers (Business)
- Creating a watcher past either cap throws
QuotaExceededError(429 QUOTA_EXCEEDED); the message names the cap you hit. Resuming one withupdate(id, { active: true })past a cap throwsValidationError(400). - A
pollIntervalbelow the minimum throwsValidationError. - A search watcher whose filters match more than 500 active listings throws
ValidationError, both oncreateand when you resume it. Oncreate, narrow it withareas,minPrice/maxPrice,beds,listingType, orbuildingType;updatecannot change filters, so to fix a resume, delete the watcher and create a narrower one. A running search watcher whose matches grow past 500 is paused. - Resuming a listing watcher whose
pollIntervalis below 3600 raises it to 3600. - Each poll counts as one request against your quota.
Watcher streams
watchers.stream(id) yields connected, change, heartbeat, reconnect, and stopped events. The server ends each stream about every 5 minutes, and the SDK reopens it by default with no limit on reconnects, resuming from the last event received. From SDK 0.8.0, a stream that closes without reconnect or stopped counts as a failed connection: it is retried with backoff, and after maxConsecutiveFailures (default 10) failed connections in a row the loop throws a ConnectionError. Every connection counts as one request against your quota, so a stream kept open around the clock costs about 12 requests an hour (about 8,640 per 30 days) on top of the polls. Pass maxReconnects to bound it, or abort signal to stop.
Error handling
The SDK throws typed errors that you can catch and handle:BoroughError. The API error classes extend it through APIError, which carries code and status; ConnectionError and PaginationLimitError extend BoroughError directly:
Retries
The SDK automatically retries rate-limit errors (RateLimitError), 5xx responses, and network failures with exponential backoff. It does not retry QuotaExceededError, because waiting does not restore quota. Default: 2 retries, starting at 500ms. For a rate-limit error, the wait is at least the retryAfter value in the error body.
TypeScript
The SDK is fully typed. All request parameters and response types are exported:Next steps
- Auto-pagination: Iterate through all pages automatically
- Webhook verification: Verify webhook signatures in Express or Next.js