Search properties
Search properties by combining a **search mode** (how filters are expressed) with a **pagination mode** (how pages are navigated). Both choices are made in the request body — no extra endpoints or query parameters needed. --- ## Search Modes Use the `searchMode` field as the discriminator. ### `classic` (default) Flat key-value filters at the root level, all combined with an implicit AND. Best for simple, well-known filter sets (the majority of use cases). ```json { "searchMode": "classic", "paginationType": "page", "page": 1, "size": 10, "transactionType": "SELL", "propertyTypes": ["FLAT", "HOUSE"], "cityIds": [1001, 1002], "price": { "gte": 100000, "lte": 500000 }, "area": { "gte": 50 }, "rooms": { "gte": 2 }, "bedrooms": { "gte": 1 } } ``` ### `advanced` A recursive `criteria` tree allowing arbitrarily nested AND / OR logic. Use this when you need complex boolean queries (e.g. "flats in Paris OR houses in Lyon with price under 300k"). **Simple leaf** (equivalent to a classic request): ```json { "searchMode": "advanced", "paginationType": "page", "page": 1, "size": 10, "criteria": { "transactionType": { "value": "SELL" }, "price": { "min": 100000, "max": 500000 }, "location": { "included": [{ "cityId": 1001 }, { "cityId": 1002 }] } } } ``` **Nested OR branch** (flats under 200k OR houses with 4+ rooms): ```json { "searchMode": "advanced", "paginationType": "page", "page": 1, "size": 10, "criteria": { "operator": "OR", "branches": [ { "propertyType": { "included": ["FLAT"] }, "price": { "max": 200000 } }, { "propertyType": { "included": ["HOUSE"] }, "rooms": { "min": 4 } } ] } } ``` --- ## Pagination Modes Use the `paginationType` field as the discriminator. ### `page` (default) Offset-based pagination. Use `page` (1-indexed) and `size`. `totalItems` is accurate up to 10,000, then capped. Supports both next and previous navigation. **First page:** ```json { "searchMode": "classic", "paginationType": "page", "page": 1, "size": 20, "transactionType": "RENT" } ``` **Navigate using `meta.pagination.nextRequestBody` from the response (page 2):** ```json { "searchMode": "classic", "paginationType": "page", "page": 2, "size": 20, "transactionType": "RENT" } ``` ### `cursor` Stable cursor-based pagination. Pass the opaque `cursor` value from the previous response. `totalItems` reflects the true count (no cap). Forward-only — no `prevRequestBody`. **Web users** are capped at 100 visible results; Partner API users have no limit. **First page:** ```json { "searchMode": "classic", "paginationType": "cursor", "size": 20, "transactionType": "SELL" } ``` **Next page — copy `meta.pagination.nextRequestBody` from the response:** ```json { "searchMode": "classic", "paginationType": "cursor", "size": 20, "transactionType": "SELL", "cursor": "<opaque cursor from previous response>" } ``` --- ## Response Structure ```json { "data": [ { "id": "/properties/018e1f9a-…", "type": "PropertySearch", "attributes": { "uuid": "018e1f9a-…", "listings": [ { "title": "Beautiful flat", "price": 250000, … } ], "minPrice": 250000, "maxPrice": 250000, "createdAt": "2025-01-01T00:00:00+00:00", "updatedAt": "2025-06-15T12:00:00+00:00" } } ], "meta": { "totalItems": 1843, "hasNextPage": true, "cursor": "eyJzb3J0IjpbMTczNjk1MjYwMDAwMCwxMjM0NV19", "pagination": { "type": "cursor", "size": 20, "nextRequestBody": { "paginationType": "cursor", "size": 20, "cursor": "eyJzb3J0IjpbMTczNjk1MjYwMDAwMCwxMjM0NV19" }, "prevRequestBody": null, "supportsPreviousPage": false, "usage": "Send a new POST /properties request using meta.pagination.nextRequestBody." } }, "links": { "self": "/properties" } } ``` > `cursor` only appears in `meta` when `paginationType` is `cursor` and `hasNextPage` is `true`. > `links.self` identifies the endpoint — pagination is request-body driven, not URL-driven. --- ## Pagination Mode Comparison | Feature | `page` | `cursor` | |---|---|---| | Parameters | `page`, `size` | `size`, `cursor` | | `totalItems` | Capped at 10,000 | True count | | Max depth | 10,000 results | Unlimited | | SAAS_USER cap | — | 100 results | | Prev-page support | ✅ | ❌ | | Default | ✅ (when `paginationType` omitted) | — | --- ## Role Restrictions | Role | Classic | Advanced | Page | Cursor | |---|---|---|---|---| | `ROLE_API_CLIENT` | ✅ Full access | ✅ Full access | ✅ Unlimited | ✅ Unlimited | | `ROLE_SAAS_USER` | ✅ Full access | ✅ Full access | ✅ Unlimited | ⚠️ Max 100 results |
Request Body
application/json
Search parameters. Use searchMode to select "classic" (default) or "advanced", and paginationType to select "page" (default) or "cursor".
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
curl -X POST "https://api-v2.stream.estate/properties" \ -H "Content-Type: application/json" \ -d '{ "searchMode": "classic", "paginationType": "page", "page": 1, "size": 20, "transactionType": "SELL", "propertyTypes": [ "FLAT", "HOUSE" ], "cityIds": [ 75056 ], "price": { "gte": 100000, "lte": 500000 }, "area": { "gte": 30 } }'{
"items": [
{
"uuid": "6e6ab049-7e39-4fbe-828b-d4b10a3ced66",
"listings": [
{
"uuid": "6e6ab049-7e39-4fbe-828b-d4b10a3ced66",
"title": "Beautiful apartment in Paris center",
"description": "string",
"url": "https://example.com/listings/123",
"price": 350000,
"currency": "EUR",
"transactionType": "SELL",
"propertyType": "APARTMENT",
"dataProvider": "seloger",
"area": 72.5,
"rooms": 3,
"bedrooms": 2,
"hasParking": true,
"hasBalcony": true,
"hasGarden": true,
"hasCellar": true,
"cityId": 42,
"cityName": "Paris",
"districtId": 7,
"districtName": "7ème arrondissement",
"neighborhoodId": 15,
"neighborhoodName": "Eiffel",
"createdAt": "2025-01-15T10:30:00+00:00",
"updatedAt": "2025-01-15T10:30:00+00:00"
}
],
"minPrice": 250000,
"maxPrice": 350000,
"createdAt": "2025-01-15T10:30:00+00:00",
"updatedAt": "2025-01-15T10:30:00+00:00"
}
],
"totalItems": 1500,
"hasNextPage": true,
"cursor": "string"
}{
"title": "string",
"detail": "string",
"status": 404,
"instance": "string",
"type": "string"
}{
"title": "string",
"detail": "string",
"status": 404,
"instance": "string",
"type": "string"
}{
"status": 422,
"violations": [
{
"propertyPath": "string",
"message": "string"
}
],
"detail": "string",
"type": "string",
"title": "string",
"instance": "string"
}