Stream EstateStream Estate
Properties

Get property by UUID

Retrieve a single property by its public UUID from Elasticsearch.

GET
/properties/{uuid}

Path Parameters

uuid*string

PropertySearch identifier

Response Body

curl -X GET "https://api-v2.stream.estate/properties/string"
{
  "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"
}
{
  "title": "string",
  "detail": "string",
  "status": 404,
  "instance": "string",
  "type": "string"
}
{
  "title": "string",
  "detail": "string",
  "status": 404,
  "instance": "string",
  "type": "string"
}

Search properties POST

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 |

List source categories GET

List source categories