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.

Last updated: 2026-04-27

/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
MethodGET
AuthX-API-Key header (B2B) or veacon_session cookie (Syncle SSO)
Quota cost1 call
Result cap200 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 so missing_periods doesn'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.

ParamTypeDefaultNotes
sigungu_codestring(all)5-digit (e.g. "11680"). Narrows to that sigungu.
property_typestring(all)office / retail / commercial_complex / mixed_use
transaction_typestring(all)sale / chartered_lease / monthly_lease
geo_precisionstringsigungudong requires Pro+.
dongstring(none)Used when geo_precision='dong'.
granularitystringquarterquarter (YYYY-Qn) or month (YYYY-MM) period buckets.
limitinteger200Result cap, [1, 500].

Response shape

json
{
  "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

FieldTypeNotes
sigungu_code / sigungustringAlways present.
gu / dongstring?Populated only when geo_precision='dong'.
property_typestringAlways present.
transaction_typestringAlways present.
earliest_periodstringLowest period (lex-sorted) with >= 2 samples.
latest_periodstringHighest period with >= 2 samples.
period_countintegerNumber of periods with data.
periods_with_datastring[]Sorted list of all periods with >= 2 samples. Drop into /pulse/series?periods=... directly.
total_samplesintegerSum of transactions across all returned periods.
samples_per_period_medianintegerMedian samples per period — surfaces variability without exposing every count.
data_sourcesstring[]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

python
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

CodeWhen
INVALID_PARAMSsigungu_code not 5-digit
INVALID_PARAMSgranularity not quarter / month
INVALID_PARAMSlimit not integer in [1, 500]
INVALID_PARAMSproperty_type / transaction_type / geo_precision outside enum
UNAUTHORIZEDMissing or invalid auth
TIER_RESTRICTEDgeo_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