GET /real-estate/coverage
Discovery endpoint — for each cohort returns earliest/latest periods, periods array, total samples, distinct sources. Plan portfolio queries before running them.
/api/v1/real-estate/coverage answers "for cohort (sigungu, property_type,
transaction_type), which periods have meaningful data?" — before the
analyst writes /pulse or
/pulse/series queries.
GET https://veacon.io/api/v1/real-estate/coverage
| Method | GET |
| Auth | X-API-Key header (B2B) or veacon_session cookie (Syncle SSO) |
| Quota cost | 1 call |
| Result cap | 200 rows by default (max 500), ordered by total_samples DESC |
When to use this
- Procurement evaluation — verify portfolio fit during the trial cycle without prior knowledge of our enum values.
- Series query planning — before calling
/pulse/series, check which periods exist somissing_periodsdoesn't dominate the response. - Dashboard discovery — drive a "what's available?" UI without hard-coding sigungu lists.
Query parameters
All optional. Calling with no filters returns the top 200 cohorts globally,
ordered by total_samples DESC — the most data-rich cohorts surface first.
| Param | Type | Default | Notes |
|---|---|---|---|
sigungu_code | string | (all) | 5-digit (e.g. "11680"). Narrows to that sigungu. |
property_type | string | (all) | office / retail / commercial_complex / mixed_use |
transaction_type | string | (all) | sale / chartered_lease / monthly_lease |
geo_precision | string | sigungu | dong requires Pro+. |
dong | string | (none) | Used when geo_precision='dong'. |
granularity | string | quarter | quarter (YYYY-Qn) or month (YYYY-MM) period buckets. |
limit | integer | 200 | Result cap, [1, 500]. |
Response shape
{
"data": [
{
"sigungu_code": "11680",
"sigungu": "강남구",
"gu": null,
"dong": null,
"property_type": "office",
"transaction_type": "sale",
"earliest_period": "2025-Q2",
"latest_period": "2026-Q1",
"period_count": 2,
"periods_with_data": ["2025-Q2", "2026-Q1"],
"total_samples": 7,
"samples_per_period_median": 4,
"data_sources": ["public_assessment", "rone_index_derived", "rtms_official"]
},
"..."
],
"_meta": {
"service": "veacon",
"api_version": "v1",
"vertical": "real_estate",
"tier": "pro",
"auth_method": "api_key",
"data_sources": ["rtms_official", "rone_index_derived", "public_assessment"],
"coverage_estimate": null,
"coverage_note": "...",
"lease_data_status": "absent",
"known_limitations": ["..."],
"disclosure_url": "https://veacon.io/data-trust",
"count": 7,
"granularity": "quarter",
"row_cap": 200,
"rate_limit": { "limit_per_min": 120, "remaining": 119 },
"request_id": "req_aB3xYz..."
}
}
Per-row fields
| Field | Type | Notes |
|---|---|---|
sigungu_code / sigungu | string | Always present. |
gu / dong | string? | Populated only when geo_precision='dong'. |
property_type | string | Always present. |
transaction_type | string | Always present. |
earliest_period | string | Lowest period (lex-sorted) with >= 2 samples. |
latest_period | string | Highest period with >= 2 samples. |
period_count | integer | Number of periods with data. |
periods_with_data | string[] | Sorted list of all periods with >= 2 samples. Drop into /pulse/series?periods=... directly. |
total_samples | integer | Sum of transactions across all returned periods. |
samples_per_period_median | integer | Median samples per period — surfaces variability without exposing every count. |
data_sources | string[] | Distinct data_source_type values across all periods (e.g. ["rtms_official", "rone_index_derived"]). |
Cohort threshold
Same as /pulse: a (cohort × period) bucket needs >= 2 samples to count
as "coverage". Single-sample buckets are excluded — they're not statistically
meaningful enough to drive a portfolio decision.
Integration pattern
from veacon import VeaconClient
client = VeaconClient(api_key="veacon_pk_...")
# 1. Discover what's available for office sales
discovery = client._http.get("/api/v1/real-estate/coverage", params={
"property_type": "office",
"transaction_type": "sale",
}).json()
# 2. Pick cohorts with at least 4 periods of data
candidates = [r for r in discovery["data"] if r["period_count"] >= 4]
# 3. Pull series for each
for cohort in candidates:
series = client.real_estate.pulse_series(
sigungu_code=cohort["sigungu_code"],
property_type=cohort["property_type"],
transaction_type=cohort["transaction_type"],
periods=cohort["periods_with_data"], # exact list, no missing periods
)
# ...
The first-class SDK method (
client.real_estate.coverage()/client.realEstate.coverage()) lands in the next SDK release. Use the raw HTTP client until then.
Errors
| Code | When |
|---|---|
INVALID_PARAMS | sigungu_code not 5-digit |
INVALID_PARAMS | granularity not quarter / month |
INVALID_PARAMS | limit not integer in [1, 500] |
INVALID_PARAMS | property_type / transaction_type / geo_precision outside enum |
UNAUTHORIZED | Missing or invalid auth |
TIER_RESTRICTED | geo_precision='dong' on Starter tier |
Empty result is success
When filters match zero cohorts, the endpoint returns 200 with an empty
data array — "nothing available" is a valid discovery answer. This differs
from /pulse and /pulse/series which return 404 when no cohort matches.
The semantic distinction: pulse/series are queries about specific data;
coverage is a query about whether data exists at all.
See also
/pulse— single-period cohort aggregate/pulse/series— multi-period/dimensions— enumerable filter values- Methodology — source provenance + DDQ pre-answer