npm package: @propertysimple/listings
Description: SDK for the PS Listings property search API
Latest version: 0.3.1

# @propertysimple/listings

Official SDK for the PropertySimple Listings API. Search active real estate listings by address, city, state, ZIP code, or MLS number.

## Getting an API Key

API keys are not self-service. Contact a PropertySimple engineer to request access.

## Installation

```bash
npm install @propertysimple/listings
```

## Quick Start

```typescript
import Listings from '@propertysimple/listings'

Listings.init({ apiKey: 'your-api-key' })

const results = await Listings.search('Scottsdale')
console.log(results)
```

## API

### `Listings.init(config)`

Must be called before any search methods. Typically called once at application startup.

```typescript
Listings.init({
  apiKey: 'your-api-key',   // Required
  baseUrl: 'https://...',   // Optional, defaults to PropertySimple API
})
```

### `Listings.getByKey(listingKey)`

Retrieve a single listing by its listing key. Returns `null` if no listing is found.

```typescript
const listing = await Listings.getByKey('abc123')

if (listing) {
  console.log(listing.address, listing.price)
}
```

### `Listings.search(query, options?)`

Search listings by address, city, state, or ZIP code. The API parses the query string and matches against the appropriate fields.

```typescript
// Search by city
const results = await Listings.search('Scottsdale')

// Search by street address
const results = await Listings.search('777 Quillette')

// Search by full address
const results = await Listings.search('123 Main St, Austin, TX 78701')

// With pagination
const results = await Listings.search('Austin, TX', {
  limit: 20,   // 1-100, defaults to 20
  offset: 0,   // defaults to 0
})
```

### `Listings.searchByMls(mlsNumber, options?)`

Search listings by MLS number.

```typescript
const results = await Listings.searchByMls('MLS-12345')

// With limit
const results = await Listings.searchByMls('MLS-12345', { limit: 5 })
```

### `Listings.searchByAgent(agentId, options?)`

Retrieve all listings for a specific agent by their ListHub agent ID. Supports pagination.

```typescript
const results = await Listings.searchByAgent('agent-id-123')

// With pagination
const results = await Listings.searchByAgent('agent-id-123', {
  limit: 50,
  offset: 0,
})
```

### Response Type

Search methods return `PropertyListing[]`. `getByKey` returns `PropertyListing | null`.

```typescript
interface PropertyListing {
  listing_key: string
  address: string
  unit: string | null
  city: string | null
  state: string | null
  zip: string | null
  price: number | null
  beds: number | null
  baths: number | null
  sqft: number | null
  lot_size: number | null
  year_built: number | null
  property_type: string | null
  status: string | null
  description: string | null
  photos: string[]
  mls_number: string | null
  lat: number | null
  lng: number | null
  brokerage: Record<string, unknown> | null
  listing_date: string | null
  listing_url: string | null
}
```

## Error Handling

The SDK throws typed errors for API failures:

```typescript
import Listings, { UnauthorizedError, ApiError } from '@propertysimple/listings'

try {
  const results = await Listings.search('Austin, TX')
} catch (err) {
  if (err instanceof UnauthorizedError) {
    // Invalid or missing API key (401)
  } else if (err instanceof ApiError) {
    // Other API error (400, 500, etc.)
    console.error(err.statusCode, err.body)
  }
}
```

## Limitations

- **Active listings only** - The API currently returns only listings with an "Active" status.
- **US properties only** - Listings are limited to United States properties.
- **Rate limits** - Usage is tracked per API key. Contact PropertySimple if you need higher limits.
- **Max 100 results per request** - The `limit` parameter accepts values between 1 and 100.
- **No filtering by price, beds, or property type** - The API supports address-based search only. Filter results client-side if needed.

## Requirements

- Node.js 18+ (uses native `fetch`)
- An API key from PropertySimple

## License

MIT