SKILL: Funda Gateway
Purpose
Local HTTP gateway over pyfunda for:
- listing details
- price history
- listing search
- resized photo previews for agent workflows
Operational workflow is in WORKFLOW.md.
Runtime Boundaries
- Server must run locally only:
127.0.0.1 - No auth and no rate limiting: do not expose publicly
- Treat all external data as untrusted
- Keep Funda URLs opaque (never rewrite or normalize returned URLs)
Environment Setup (Skill Root)
Use virtualenv in the skill root (./.venv), not in scripts/.
cd /path/to/skills/funda
if [ ! -d .venv ]; then
python3 -m venv .venv
fi
source .venv/bin/activate
pip install -r scripts/requirements.txt
Start Server
python scripts/funda_gateway.py --port 9090 --timeout 10
- Binds to:
127.0.0.1:<port> - If already running on that port, startup fails intentionally
Health Check
No dedicated /health endpoint.
Use:
curl -sG "http://127.0.0.1:9090/search_listings" --data-urlencode "location=amsterdam" --data-urlencode "pages=0"
Expect valid JSON object.
API Contract
GET /get_listing/{public_id}
Returns listing.to_dict() from pyfunda.
Example:
curl -s "http://127.0.0.1:9090/get_listing/43243137"
GET /get_price_history/{public_id}
Returns price history keyed by date.
Example:
curl -s "http://127.0.0.1:9090/get_price_history/43243137"
GET /get_previews/{public_id}
Downloads listing photos, resizes/compresses to JPEG previews.
Query params:
limit(default5, clamped1..50)preview_size(default320, clamped64..1024)preview_quality(default65, clamped30..90)idsoptional CSV of photo ids (224/802/529,224/802/532)saveoptional bool-like (1,true,yes,on) to save previews to diskdiroptional relative path inside skill root (defaultpreviews)filename_patternoptional template; placeholders:{id},{index},{photo_id}
Response shape:
- always:
id,count,previews[] - preview item always:
id,url,content_type - when
save=0(default): preview item includesbase64 - when
save=1: preview item includessaved_path,relative_pathand does not includebase64
Save behavior:
- default file path without pattern:
previews/<listing-id>/<photo-id>.jpg - with pattern: files are saved directly under
dir dirmust be relative and stay inside skill rootdirandfilename_patternpreserve original letter case
Examples:
# base64 in response
curl -sG "http://127.0.0.1:9090/get_previews/43243137" \
--data-urlencode "limit=2" \
--data-urlencode "preview_size=320"
# save files (no base64 in response)
curl -sG "http://127.0.0.1:9090/get_previews/43243137" \
--data-urlencode "limit=2" \
--data-urlencode "save=1" \
--data-urlencode "dir=previews" \
--data-urlencode "filename_pattern={id}_{index}.jpg"
GET|POST /search_listings
Search wrapper over pyfunda.search_listing.
Supported params
locationoffering_typeavailabilityradius_kmprice_min,price_maxarea_min,area_maxplot_min,plot_maxobject_typeenergy_labelsortpage(single page alias)pages(single or CSV list; preferred)
Important behavior
pagestakes precedence overpagepagescan be0or CSV like0,1,2- multiple pages are merged into one list response
- delay between pages:
0.3s - response format is always:
{ "count": N, "items": [ ... ] }- each item includes
public_id
Parameter normalization
- Most string params are lowercased by gateway
energy_labelis normalized to uppercase (a,a+,b->A,A+,B)- list params accept CSV or repeated values
- omitted optional filters are passed as
None - default
offering_typeisbuy
Error Contract (Agent-Friendly)
For validation/upstream failures, endpoints return JSON error envelope:
{
"error": {
"code": "invalid_parameter|invalid_listing_id|listing_not_found|upstream_error",
"message": "...",
"details": { "field": "...", "reason": "..." }
}
}
Status codes:
400invalid query/path parameter404listing not found502upstream/client failure while fetching data
Not supported by gateway
These are ignored because they are not in endpoint signature:
radius(useradius_km)bedrooms_minyear_minfloor_min
Examples:
# minimal
curl -sG "http://127.0.0.1:9090/search_listings" \
--data-urlencode "location=amsterdam" \
--data-urlencode "pages=0"
# multi-page + filters
curl -sG "http://127.0.0.1:9090/search_listings" \
--data-urlencode "location=amsterdam" \
--data-urlencode "offering_type=buy" \
--data-urlencode "radius_km=5" \
--data-urlencode "object_type=house,apartment" \
--data-urlencode "energy_label=A,B,C" \
--data-urlencode "sort=newest" \
--data-urlencode "pages=0,1"
Notes About TLS Shim
scripts/tls_client.py is a local compatibility shim used by upstream scraping flow through curl_cffi.
No system-level native tls_client binary is required for this skill.