Filtering & sorting
Every list endpoint accepts filters as query parameters and a single order-by. The tables below list exactly what each entity supports — reach for a parameter that isn't here and you'll get a 422 naming the valid options. Filters narrow server-side, so you never download rows you'll discard. Pair this with Paginationfor stable, complete reads.
Property
| Filter | Match | Notes |
|---|---|---|
| status | exact | snake_case enum value |
| type | exact | snake_case enum value |
| name | contains | case-insensitive substring |
| x_id | exact | the native PMS identifier |
| integration_id | exact | scope to one connected source |
To fetch a single property by its PropSocket id, use GET /v1/properties/{id} — there's no id filter on the list endpoint.
Unit
| Filter | Match | Notes |
|---|---|---|
| property_id | exact | units within one property |
| status | exact | |
| type | exact | |
| unit_number | exact | |
| building | exact | |
| bedrooms_gte / bedrooms_lte | range | inclusive bounds |
| bathrooms_gte / bathrooms_lte | range | inclusive bounds |
| x_id | exact |
Resident
| Filter | Match | Notes |
|---|---|---|
| property_id | exact | residents on a lease at this property |
| lease_id | exact | residents on a specific lease |
| status | exact | |
| type | exact | |
| first_name | contains | case-insensitive substring |
| last_name | contains | case-insensitive substring |
| x_id | exact |
property_id and lease_id traverse the lease-resident relationship, so a resident on more than one matching lease is returned once, not duplicated.
Lease
| Filter | Match | Notes |
|---|---|---|
| property_id | exact | |
| unit_id | exact | |
| resident_id | exact | leases a resident is on |
| status | exact | |
| type | exact | |
| start_date_gte / start_date_lte | range | YYYY-MM-DD, inclusive |
| end_date_gte / end_date_lte | range | YYYY-MM-DD, inclusive |
| x_id | exact |
A lease's residents are nested in the response as a relation array — LeaseResident is relation-only, with no top-level collection of its own.
Combinator semantics
Different filters combine with AND — every parameter you add narrows the result further. There is no nesting and no NOT in the current version.
# Different filters combine with AND. This returns active apartments in one property.
curl "https://api.propsocket.io/v1/units?property_id=prp_01HX0G5T8N3KEWBYV2QMR4DCFA&status=active&type=apartment" \
-H "Authorization: Bearer ps_test_YOUR_TEST_KEY"For OR within a single field, pass a comma-separated list — the filter matches any value in it. There is no OR across different fields; for that, make separate requests and union the results yourself.
# A single filter accepts a comma-separated list — matches ANY value (OR within the field).
# "active OR pending" units:
curl "https://api.propsocket.io/v1/units?status=active,pending" \
-H "Authorization: Bearer ps_test_YOUR_TEST_KEY"Range filters
Numeric and date ranges use _gte / _lte pairs (greater-than-or-equal, less-than-or-equal). Send one or both bounds.
# Range filters use _gte / _lte pairs. Two- and three-bedroom units:
curl "https://api.propsocket.io/v1/units?bedrooms_gte=2&bedrooms_lte=3" \
-H "Authorization: Bearer ps_test_YOUR_TEST_KEY"Time-window filters
Every entity supports time-window filters on its system timestamps:updated_after, created_after, and created_before, each taking a UTC ISO 8601 value. These are the backbone of incremental sweeps — pull only what changed since your last watermark instead of re-reading the whole collection. Pairupdated_after with order-by=updated_at:asc for a stable, resumable walk.
# Time-window filters on every entity, by created_at / updated_at.
# Everything changed since your last sweep:
curl "https://api.propsocket.io/v1/leases?updated_after=2026-05-20T00:00:00Z&order-by=updated_at:asc" \
-H "Authorization: Bearer ps_test_YOUR_TEST_KEY"Sorting
Sort with a single order-by=field:asc|desc. The default iscreated_at:desc. For stable, resumable pagination, sort by created_at:ascso newly inserted rows append to the end of the sequence rather than shifting earlier pages.
# order-by is field:asc|desc. Default is created_at:desc.
curl "https://api.propsocket.io/v1/leases?order-by=start_date:asc" \
-H "Authorization: Bearer ps_test_YOUR_TEST_KEY"Each entity sorts on a defined set of fields. Ask for a field an entity doesn't expose and you'll get a 422 listing the valid ones — see Errors.
Soft-deleted records
List and retrieve endpoints exclude soft-deleted records by default. To include them — to reconcile removals or audit deletions — add ?include_deleted=true and read each record's deleted_at.
Next
Filters compose with paging — see Pagination for the envelope and the loop, and the nightly units CSV recipe for filtering and paging together in one job.