Property Sources
Discover connected property sources and use one search, detail, location and option contract.
Use /property-sources to discover the sources available to your organization.
The same endpoints accept a property API key or an authenticated dashboard JWT
with an active organization. Source credentials belong to that organization;
a source connected elsewhere does not become available to your key.
Endpoints
| Method | Path | Result |
|---|---|---|
GET | /property-sources | Source descriptors and current organization connectivity |
POST | /property-sources/:source/search | Unified listings, receipt and optional continuation |
GET | /property-sources/:source/detail/:id?country= | One unified listing with its receipt |
GET | /property-sources/:source/locations?q=&country= | Location choices with opaque locationId values |
GET | /property-sources/:source/options/:facet | Supported option values, labels and optional aliases |
POST | /property-sources/search | One to five sources in one interleaved page (signed-in dashboard sessions only) |
GET | /property-sources/allowance | Today's use of the daily portal allowance (signed-in dashboard sessions only) |
Discover capabilities
curl https://api.fondaro.com/property-sources \
-H "Authorization: ApiKey fondaro_pk_abc123"Each descriptor includes id, label, family, connected, connection,
country information and capabilities. A disconnected source can include a
display-safe reason.
connection is the verified state for your organization:
connection.status | Meaning |
|---|---|
connected | The saved credentials passed their latest live check (the Fondaro network is always connected; a property portal is connected when Fondaro's shared RealtyAPI key is configured, since portals have no per-organization credential). |
attention | Credentials are saved but the latest check failed or could not run. connection.reason is one of credentials_incomplete, credentials_rejected, access_refused, provider_unavailable, network_unavailable or check_failed, and connection.message says what to fix. |
disconnected | Nothing is saved for this source. |
connected is true only when connection.status is connected; it is kept
for existing clients. A source that needs attention is refused like a
disconnected one (PROPERTY_SOURCE_NOT_CONNECTED). Checks are cached per
organization and credential for 6 hours after a pass and 5 minutes after a
failure; changing the credentials checks them again on the next read.
{
"id": "zoddak",
"label": "Zoddak",
"connected": false,
"reason": "Zoddak did not accept this API token. Copy it again from your Zoddak portal, disconnect, and save the new one.",
"connection": {
"status": "attention",
"reason": "credentials_rejected",
"message": "Zoddak did not accept this API token. Copy it again from your Zoddak portal, disconnect, and save the new one.",
"checkedAt": "2026-09-24T10:15:00.000Z"
}
}Capabilities describe supported views, detail, adding by link, brochure
eligibility, image policy, spend and filter facets. Use these fields to build
controls; a returned listing field does not imply a corresponding search filter.
brochureImageLimit, when present, is the number of photos a brochure keeps
from one listing. nativePageSize, when present (the property portals), is the
number of rows in one of the source's own result pages. detailOptions lists the extra detail-request options a
source honours. Resales Online declares viewerId (opening a listing through
an agency's property-viewer share link). Fondaro uses it server-side for
brochures. The HTTP detail endpoint accepts only country, and a viewer id is
never part of a listing ref.
A facet can require a value, expose discoverable options, support multiple
values, constrain a numeric range or name supported geometries. Respect its
min, max, integer, range and rangeConstraint fields. verifiable describes
whether returned facts can verify a filter; the search receipt records what was
verified for that particular response.
Canonical source ids are internal (the Fondaro network), resales_online, zoddak,
inmobalia, and the portal ids idealista, rightmove, immobiliare,
immoscout, funda, zoopla, seloger, otodom, immowelt, realtor,
homes, trulia, propertyfinder, dubizzle, centris, loopnet, zillow,
redfin and bayut. Use the canonical id in the URL. Stored client-site aliases
such as fondaro and resales-online are not endpoint source ids.
Search
Search one source with the fields its descriptor supports. Unknown fields, unsupported filters and invalid values fail explicitly; criteria are never silently relaxed.
curl -X POST https://api.fondaro.com/property-sources/internal/search \
-H "Authorization: ApiKey fondaro_pk_abc123" \
-H "Content-Type: application/json" \
-d '{"scope":"own","minPrice":250000,"minBedrooms":3,"limit":10}'| Input | Meaning |
|---|---|
scope | own or network on sources that advertise scope; Fondaro defaults to active network listings. Signed-in dashboard sessions may also send partners or followed |
organizationId, agentUserId | Signed-in dashboard sessions only: one agency's (or one of its agents') network listings, on sources that advertise scope |
openHouseWithinDays | Signed-in dashboard sessions only: 1 to 14; only listings with a published open house for other agencies that has not ended and starts within that many days |
query | Text search, when supported |
locationIds | Opaque tokens returned by this source's location endpoint |
locations | Signed-in dashboard sessions only: stored location objects from location rows, instead of locationIds |
country | Backend country selected from the descriptor |
operation, propertyTypes, features, stages, statuses, sort | Source-supported option values |
minPrice, maxPrice | Price bounds |
minBedrooms, maxBedrooms, minBathrooms, maxBathrooms | Bedroom and bathroom bounds |
minRooms, maxRooms | Total-room bounds, distinct from bedrooms |
minBuildSize, maxBuildSize, minPlotSize, maxPlotSize | Area bounds |
referenceNumbers | Exact listing references, when supported |
newDevelopments | Development filter, when supported |
geo | A supported circle, polygon or boundingBox |
limit | Page size from 1 to 20 |
cursor | Opaque continuation from an earlier response |
ImmoScout, Immobiliare and Otodom filter total rooms using minRooms, with
integer minima. Otodom accepts up to ten. These sources do not advertise bedroom
filters or room maxima. Returned room facts can still contain halves, ranges or
an open upper bound (roomsTo: null). Genuine detail bedrooms remain separate.
The optional sources array accepts exactly one source matching the URL:
this route searches the source its URL names, and more than one entry returns
MULTI_SOURCE_NOT_SUPPORTED. To search one or more sources through one door, see
One to five sources in one search. An optional
body source must also match the URL.
Search responses include source, showing, results and receipt. The
count has three states:
| Response | Meaning |
|---|---|
total without totalIsLowerBound | Exact number of matches |
total with totalIsLowerBound: true | At least that many; the source stopped counting |
No total | Unknown: the provider did not supply a reliable count, or this is a continuation page |
The Fondaro network counts on the first page only, up to 10,000: beyond that it returns
total: 10000 with totalIsLowerBound: true, and later pages carry no count.
Keep the first page's count while you page. Other sources never set
totalIsLowerBound. Treat nextCursor as the continuation authority rather
than calculating pages from total. To continue, send the cursor to the same
source:
{ "cursor": "<nextCursor from the preceding response>" }Cursors bind organization, source, criteria and page size. Reset pagination when
any of those changes. Provider sessions remain inside the opaque cursor; do not
extract or submit a separate Resales query id. An expired or mismatched cursor
returns PROPERTY_CURSOR_INVALID; restart the search with its original criteria.
The receipt contains requested and resolved criteria, applied facets, redacted
provider parameter names and excludedUpstreamMismatches. result_verified
means returned facts support the applied filters. wire_applied_only means the
request was mapped to the provider but some response facts could not verify it.
One to five sources in one search
POST /property-sources/search runs one set of criteria over 1 to 5 sources
and returns one interleaved page. It is available to signed-in dashboard
sessions only: a property API key receives 401. Keys, MCP and the assistant
keep the one-source route for now.
curl -X POST https://api.fondaro.com/property-sources/search \
-H "Authorization: Bearer <dashboard session token>" \
-H "Content-Type: application/json" \
-d '{
"sources": ["internal", "resales_online", "idealista"],
"placeIds": ["<place id from GET /places>"],
"propertyTypes": ["villa"],
"minBedrooms": 3,
"maxPrice": 1200000,
"sort": "mixed",
"unsupportedFacets": "ignore"
}'| Input | Meaning |
|---|---|
sources | 1 to 5 distinct source ids, in display order. Always explicit; there is no "all sources" |
placeIds | 1 to 5 place ids from GET /places; not combinable with geo |
sort | mixed (default), price_asc or price_desc |
cursor | The previous page's nextCursor; anything sent beside it must repeat the original request |
scope | own, network, partners or followed, sent only to sources that advertise scope (the Fondaro network); other sources are searched without it and never dropped for it |
organizationId | One agency's network listings, on the same sources as scope |
openHouseWithinDays | 1 to 14, on the same sources as scope (see the one-source table) |
unsupportedFacets | drop_source (default) or ignore: what a source that cannot apply a requested filter does (below) |
| Criteria | The one-source search fields (propertyTypes, minPrice, minBedrooms, features, geo, …) except agentUserId, locationIds, locations, sort and limit |
Filters are an intersection, never widened silently. Each source compiles
the request through its own contract. By default (drop_source), a source that
does not offer a requested filter is not searched: its receipt says dropped: { "reason": "facet_unsupported", "facets": [...] }. With unsupportedFacets: "ignore", the source is searched without the filters it lacks, and without
option values it cannot resolve, and its receipt names them in ignoredFacets
(for example ["bathrooms"]), so the caller can say "not applied on this
source". A place is never ignored: a source that cannot filter by place is
still dropped. A source with a total-rooms filter and no bedroom filter
receives the bedroom minimum as rooms. Filters a source applies but cannot check against its rows keep
verification: "wire_applied_only" on that source's receipt.
Places. Each source receives its own location value for a place. When a
source has no value for a place yet, Fondaro looks the place name up once at
that source (on a portal this costs one unit of the daily allowance, shown as
placeLookupUnits) and remembers an exact match. A place the source still
cannot name, or whose country the source does not serve, drops that source
with place_unresolved. Inmobalia has no location filter, so any placeIds
drop it. A source your organization has not connected is dropped with
not_connected.
Fondaro network rows default to the network scope: every agency's active
listings, including your own. scope: "own" narrows them to your agency's
active listings.
Order. mixed takes rows in turn from each source in the order of
sources, each source in its own default order. price_asc and price_desc
compare the price in EUR (USD converts at the latest stored rate; another
currency, or no price, sorts last); ties keep source order. A source that
offers the same sort receives it too. There is no newest or relevance sort
across sources.
Pages. Each page asks every source that still has results for its next
12 rows and orders that batch, so order is per page, not across pages.
nextCursor is absent when every source is exhausted. A cursor expires after
10 minutes and belongs to your organization and the original request; a
changed request returns PROPERTY_CURSOR_INVALID.
Time limit. A source that has not answered within 8 seconds is reported
in errors with PROPERTY_SOURCE_TIMEOUT and retryable: true, and the other
sources' rows are returned. Loading more tries it again. A portal unit it
already spent stays spent and appears on its receipt.
Duplicates are grouped, never removed. groups lists rows of this page
that are the same home: imported_from when a Fondaro network listing was imported
from another row on the page (Fondaro rows carry importedFrom: { source, id }
for imported listings), and same_home when rows of different sources are
within 100 metres, within 2% in EUR and have the same bedrooms. Show a group
as one card with "Also on …".
{
"sources": ["internal", "resales_online", "idealista"],
"sort": "mixed",
"results": [
{ "id": "…", "source": "internal", "ref": { "source": "internal", "id": "…" }, "importedFrom": { "source": "resales_online", "id": "R4381122" } },
{ "id": "R4381122", "source": "resales_online", "ref": { "source": "resales_online", "id": "R4381122" } },
{ "id": "i1", "source": "idealista", "ref": { "source": "idealista", "id": "i1", "country": "es" } }
],
"receipts": {
"internal": { "source": "internal", "verification": "result_verified", "upstreamUnits": 0, "placeLookupUnits": 0 },
"resales_online": { "source": "resales_online", "verification": "result_verified", "upstreamUnits": 0, "placeLookupUnits": 0 },
"idealista": { "source": "idealista", "verification": "result_verified", "upstreamUnits": 1, "placeLookupUnits": 1 }
},
"totals": { "internal": 41, "resales_online": 118 },
"totalIsLowerBound": {},
"errors": {},
"groups": [
{
"id": "group:…",
"refs": [
{ "source": "internal", "id": "…" },
{ "source": "resales_online", "id": "R4381122" }
],
"reason": "imported_from"
}
],
"nextCursor": "<opaque>"
}Receipts are shortened above; each also carries the usual requested,
resolved, appliedFacets, wireFacets, criteriaLabel and
excludedUpstreamMismatches. A dropped or failed source's receipt has its
requested criteria and an empty resolution: read dropped and errors first.
totals has per-source counts where the source counts, on the first page
only; there is no total across sources.
Allowance
GET /property-sources/allowance returns today's use of the organization's
daily portal allowance (the one the dashboard, MCP, the assistant and API keys
draw). The dashboard shows what is left under Sites in Search once some is used:
{ "used": 86, "limit": 300, "resetsAt": "2026-09-25T00:00:00.000Z" }A search over several portals costs up to one unit per portal per page (none
on a cache hit), plus one unit for each first-time place lookup on a portal.
upstreamUnits on a portal's receipt is 0 when its page came from the cache.
Locations, options and identity
Discover options using the advertised facet, such as
/property-sources/internal/options/property_type or
/property-sources/internal/options/scope. The response is an array of
{ "value": "...", "label": "..." } choices, with optional family and aliases.
Location responses contain locationId, label and optional type and parent.
Pass the complete token to search; tokens belong to the organization and source
that issued them and expire after 15 minutes. Portal tokens also bind the
backend country. Fondaro, Resales and Zoddak location discovery reject a country
qualifier rather than silently ignoring it.
Fondaro network location rows come in three kinds (type): city rows for the
towns you can see, community rows (an area within a town, whose parent is
the town) and region rows. Several locations in one search match a listing in
any of them, so Benahavís with Nueva Andalucía returns both. A community
matches only inside its own town, because one community name can exist in two
towns.
Location is optional for the Fondaro network, Resales Online and Zoddak: a search
without one covers the whole feed. Inmobalia has no location filter. Portals
require a location or a supported geo shape.
In a signed-in dashboard session (not with an API key), each location row also
carries location: { kind, value, label, parent?, country? }. It does not
expire, so the dashboard stores it in saved views and tabs and sends it back as
locations in place of locationIds. The search applies it to the same source
and organization and verifies it like a token, including the portal backend
country. API keys that send locations get PROPERTY_FILTER_VALUE_INVALID.
Every new search and detail row carries ref: { source, id, country? }. Preserve
the entire reference in selections, links and caches. Identical portal ids in
different countries refer to different listings. Fondaro ids are UUIDs;
referenceNumber is a separate display and search field. Provider ids are
opaque strings: URL-encode the whole id when fetching detail, including any
slashes, colons or Unicode characters, and forward its country qualifier.
Fondaro network (internal) search defaults to the network scope: active listings
from every agency on Fondaro. An active listing from another agency includes its
street address, postcode and exact coordinates, in search and detail alike. Only
the listing agency's private commission is withheld. Another agency's
non-active listing is not returned, and its detail returns
PROPERTY_SOURCE_LISTING_NOT_FOUND. Use scope: "own" to search your own
listings.
Errors and metering
Typed errors include code, a safe message, and, for search errors, source
and nextAction. Unsupported filters, invalid options, missing required
locations, disconnected sources and expired cursors are explicit failures.
PROPERTY_SOURCE_LISTING_NOT_FOUND identifies an unavailable detail;
PROPERTY_UPSTREAM_FAILED identifies a provider failure;
PROPERTY_SOURCE_TIMEOUT (several-source search only) identifies a source that
did not answer in time. Handle the code rather than matching message text.
Each portal source meters itself: it consumes one unit of the organization's
daily allowance per real call to the paid provider, whichever endpoint, tool or
brochure caused it. Shared cache hits and repeated cached missing-detail results do not
consume another unit. PROPERTY_PORTAL_QUOTA_EXHAUSTED reports exhaustion.
HTTP request rate limits still apply to cached responses; see
API Overview.
Related Articles
Authentication
Create, scope, rotate and revoke Fondaro API keys, restrict them to your website's origin, and read their rate limits.
Fondaro Property Search
Search and filter property listings with text queries, location filters, geo search, and more.
Property Brochures
Create and manage shareable interactive property brochures through the authenticated REST API or Fondaro MCP.