{"openapi":"3.1.0","info":{"title":"QuakePulse Earth Intelligence Platform API","version":"1.0.0","x-platform":"earth-intelligence","description":"Multi-domain Earth intelligence: air quality, seismic activity, ocean conditions, agricultural stress, and urban change — all on one platform. Public domain, World State, evidence-query, and corpus endpoints require no authentication. The API-key surface is explicitly marked per operation. The public Zeno/Divergent corpus is an append-only, availability-aware evidence contract: issue time, target time, outcome-vintage time, revision, native units, lineage, and missingness must be preserved. It does not establish trust, surprise, health, reliability, failure probability, best-model claims, or a universal risk score. PM10 remains quarantined pending independently approved recovery evidence. Global Context is evidence-only and cannot become a score, probability, confidence value, causal driver, severity adjustment, or forecast input. Discover capabilities at GET /v1/capabilities, access governance at GET /v1/access-policy, and corpus metadata at GET /corpus/v1/meta.","contact":{"name":"Notflat Developer Support","url":"https://notflat.world/developers"},"license":{"name":"Commercial","url":"https://notflat.world/developers"}},"servers":[{"url":"https://notflat.world/api","description":"Production"}],"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"Capabilities","description":"Platform-wide domain and capability discovery. No authentication required."},{"name":"Auth","description":"Verify your API key and inspect tier/quota."},{"name":"Wards","description":"Per-ward current readings and 72-hour forecasts (Delhi/Mumbai). Auth required."},{"name":"Delhi","description":"City-level smoke trajectory and source attribution. Auth required."},{"name":"Seismic","description":"Global earthquake events, tectonic zone ML anomalies, and escalation forecasts. Public."},{"name":"Marine","description":"Ocean conditions, reef/chlorophyll scenes, and coastal alerts. Public."},{"name":"Agriculture","description":"Crop stress, burn activity, and district biophysical signals. Public."},{"name":"Urban","description":"Urban satellite change detection, heat island, and water quality. Public."},{"name":"CompoundRisk","description":"Cross-domain compound risk events (heat+air, flood+disease, fire+smoke). Public."},{"name":"CompoundRiskV1","description":"Evidence-linked compound risk (v1). Each event cites stable EvidenceEnvelope IDs, combination methodology, time/spatial alignment, confidence level, and limitations. Auth required."},{"name":"DataHealth","description":"Platform data source freshness and feed status. Public."},{"name":"EvidenceQuery","description":"Unified cross-domain spatial/temporal evidence query. Public, optional API key."},{"name":"AssetExposure","description":"Batch asset exposure — returns per-domain exposure signals for caller-supplied asset geometries. Auth required."},{"name":"SatelliteArchive","description":"Satellite coverage check, scene list, and tasking-readiness metadata from the Open Cosmos archive. Auth required. No live OC API calls — queries the platform's own mirrored scene table."},{"name":"SatelliteTasking","description":"Approval-gated satellite tasking requests. Submit an area-of-interest and observation window for human review. No Open Cosmos acquisition is scheduled until a platform operator explicitly approves via the admin API. Requires the `satellite_tasking` role on your API key."},{"name":"Corpus","description":"Public, read-only, incrementally pageable Zeno/Divergent corpus for air, earth, agriculture, sea, urban, and global-context. Availability bounds, opaque cursors, revisions, native units, and append-only lineage are part of the contract; no authentication required."},{"name":"GlobalIntelligence","description":"Normalized, source-attributed signals from seven public providers. Authenticated read-only access; provider-specific freshness and limitations are explicit."},{"name":"WorldState","description":"Public State Layer discovery and bounded values over existing evidence, lineage, models, scoring, and Global Context records."},{"name":"Worldline","description":"Authenticated bounded, reproducible graphs that project World State, corpus, global context, model lifecycle, alerts, and operational qualifications."}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key","description":"Pass your API key in the `Authorization: Bearer <key>` header, or alternatively as `X-API-Key: <key>`. Existing keys retain wildcard compatibility; newly issued keys use scopes such as v1:read, v2:read, asset:read, satellite:read, worldline:read, and claim:read. See GET /v1/access-policy for reset, alias, and migration rules.","x-scopes":["v1:read","v2:read","evidence:read","asset:read","satellite:read","satellite:task","worldline:read","claim:read"]}},"schemas":{"StateLayerRecipe":{"type":"object","required":["id","version","direct_inputs","source_constraints","unit_conversion","temporal_alignment","spatial_mapping","joins","quality_exclusions","missing_value_behavior","equation_or_model","output_semantics"],"properties":{"id":{"type":"string"},"version":{"type":"string"},"direct_inputs":{"type":"array","items":{"type":"string"}},"source_constraints":{"type":"array","items":{"type":"string"}},"unit_conversion":{"type":"string"},"temporal_alignment":{"type":"string"},"spatial_mapping":{"type":"string"},"joins":{"type":"array","items":{"type":"string"}},"quality_exclusions":{"type":"array","items":{"type":"string"}},"missing_value_behavior":{"type":"string"},"equation_or_model":{"type":"string"},"output_semantics":{"type":"string"}}},"StateLayerDeclaration":{"type":"object","required":["id","semantic_version","name","description","domain","category","physical_or_statistical_meaning","valid_units","value_constraints","native_resolution","delivered_resolution","cadence","methodology_version","evidence_role","claim_posture","availability_requirements","redistribution_status","recipe","source_channels","runtime","links"],"properties":{"id":{"type":"string","description":"Stable State Layer identifier."},"semantic_version":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context","cross-domain"]},"category":{"type":"string","enum":["direct_measurement","normalized_measurement","derived_indicator","fused_indicator","inferred_state","model_output","forecast_nowcast","scenario_planning"]},"physical_or_statistical_meaning":{"type":"string"},"valid_units":{"type":"array","minItems":1,"items":{"type":"string"}},"value_constraints":{"type":"object","additionalProperties":true},"native_resolution":{"type":"string"},"delivered_resolution":{"type":"string"},"cadence":{"type":"string"},"methodology_version":{"type":"string"},"evidence_role":{"type":"string","enum":["measurement","derived_evidence","model_evidence","context"]},"claim_posture":{"type":"string","enum":["supported","provisional","not_claimed"]},"availability_requirements":{"type":"array","items":{"type":"string"}},"redistribution_status":{"type":"string","enum":["allowed_with_attribution","source_specific","restricted_non_commercial"]},"recipe":{"anyOf":[{"$ref":"#/components/schemas/StateLayerRecipe"},{"type":"null"}]},"source_channels":{"type":"array","items":{"type":"string"}},"runtime":{"type":"object","required":["status","reason","checked_at","matched_count","latest_available_at"],"properties":{"status":{"type":"string","enum":["available","stale","missing","rights_blocked","unavailable","unknown"]},"reason":{"type":"string"},"checked_at":{"type":"string"},"matched_count":{"type":["integer","null"]},"latest_available_at":{"type":["string","null"],"format":"date-time"}}},"links":{"type":"object","additionalProperties":{"type":["string","null"]}}}},"StateLayerValue":{"type":"object","required":["layer","layer_version","domain","category","entity_id","geometry","target_time","reference_period","observed_at","issue_time","available_at","retrieved_at","value","value_text","unit","uncertainty","quality","source","lineage","claim_posture","revision","revision_id","revision_of","links"],"properties":{"layer":{"type":"string"},"layer_version":{"type":"string"},"domain":{"type":"string"},"category":{"type":"string"},"entity_id":{"type":"string"},"geometry":{"type":["object","null"],"additionalProperties":true},"target_time":{"type":["string","null"],"format":"date-time"},"reference_period":{"type":["string","null"]},"observed_at":{"type":["string","null"],"format":"date-time"},"issue_time":{"type":["string","null"],"format":"date-time"},"available_at":{"type":["string","null"],"format":"date-time"},"retrieved_at":{"type":["string","null"],"format":"date-time"},"value":{"type":"number","description":"Always finite. Missing data is represented by the absence/status of a value, never by an invented zero."},"value_text":{"type":["string","null"],"description":"Categorical state label or event reference where applicable; numeric value remains finite and machine-sortable."},"unit":{"type":"string"},"uncertainty":{"type":"object","additionalProperties":true},"quality":{"type":"object","additionalProperties":true},"source":{"type":"object","additionalProperties":true},"lineage":{"type":"object","additionalProperties":true},"claim_posture":{"type":"string","enum":["supported","provisional","not_claimed"]},"revision":{"type":"integer","minimum":1},"revision_id":{"type":"string"},"revision_of":{"type":["string","null"]},"links":{"type":"object","additionalProperties":true}}},"WorldStateLayersResponse":{"type":"object","required":["schema_version","semantic_version","product","description","architecture","layers","layer_count","filters","examples"],"properties":{"schema_version":{"type":"string"},"semantic_version":{"type":"string"},"product":{"type":"string","const":"World State"},"description":{"type":"string"},"architecture":{"type":"object","additionalProperties":true},"layers":{"type":"array","items":{"$ref":"#/components/schemas/StateLayerDeclaration"}},"layer_count":{"type":"integer"},"filters":{"type":"object","additionalProperties":true},"examples":{"type":"object","additionalProperties":{"type":"string"}}}},"WorldStateValuesResponse":{"type":"object","required":["schema_version","data","pagination","meta"],"properties":{"schema_version":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/StateLayerValue"}},"pagination":{"type":"object","required":["limit","returned","has_next_page","next_cursor","ordering"],"properties":{"limit":{"type":"integer","minimum":1,"maximum":100},"returned":{"type":"integer"},"has_next_page":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"ordering":{"type":"array","items":{"type":"string"}}}},"meta":{"type":"object","additionalProperties":true}}},"WorldlineResponse":{"type":"object","required":["graph","meta"],"properties":{"graph":{"type":"object","required":["schema_version","protocol","type","nodes","edges"],"properties":{"schema_version":{"type":"string","example":"1.0.0"},"protocol":{"type":"string","const":"planetary-worldline/v1"},"type":{"type":"string","const":"worldline"},"nodes":{"type":"array","items":{"type":"object","additionalProperties":true}},"edges":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"meta":{"type":"object","required":["query_plan_hash","continuation_cursor","coverage","rights","citation","gaps"],"additionalProperties":true}}},"WorldlineUnavailableResponse":{"type":"object","required":["error","availability","suppressed","message"],"properties":{"error":{"type":"string","const":"worldline_unavailable"},"availability":{"type":"string","const":"unavailable"},"suppressed":{"type":"boolean","const":true},"message":{"type":"string"}}},"CorpusLineageEntry":{"type":"object","required":["provider_id","provider_name","role","evidence_type","evidence_id","source_record_id","scene_id","collection","observed_at","captured_at","ingested_at","stage","linkage_quality"],"properties":{"provider_id":{"type":"string","description":"Canonical machine-readable provider identifier."},"provider_name":{"type":"string"},"role":{"type":"string","enum":["measurement","derived_input","model_input","model_producer","training_dataset"]},"evidence_type":{"type":"string","enum":["database_record","feature_snapshot","satellite_scene","scene_analysis","model_artifact","training_dataset"]},"evidence_id":{"type":"string"},"source_record_id":{"type":["string","null"]},"scene_id":{"type":["string","null"]},"collection":{"type":["string","null"]},"observed_at":{"type":["string","null"],"format":"date-time"},"captured_at":{"type":["string","null"],"format":"date-time"},"ingested_at":{"type":["string","null"],"format":"date-time"},"stage":{"type":"string"},"linkage_quality":{"type":"string","enum":["exact","partial"]},"metadata":{"type":"object","additionalProperties":true}}},"ModelBehaviourContract":{"type":"object","required":["contract_version","evidence_only","derived_conclusions_excluded","resources","query_support"],"properties":{"contract_version":{"type":"string","const":"1.0.0"},"evidence_only":{"type":"boolean","const":true},"derived_conclusions_excluded":{"type":"array","items":{"type":"string"}},"resources":{"type":"array","items":{"type":"string"}},"query_support":{"type":"object","required":["available_after","available_before","opaque_cursor"],"properties":{"available_after":{"type":"boolean","const":true},"available_before":{"type":"boolean","const":true},"opaque_cursor":{"type":"boolean","const":true}}}}},"ModelBehaviourPopulationQuality":{"type":"object","required":["model_count","provider_count","family_count","independent_model_count","forecast_event_count","peer_named_event_count","uncertainty_event_count","outcome_vintage_count","operational_event_count","completeness_status","reason"],"properties":{"model_count":{"type":["integer","null"]},"provider_count":{"type":["integer","null"]},"family_count":{"type":["integer","null"]},"independent_model_count":{"type":["integer","null"]},"forecast_event_count":{"type":["integer","null"]},"peer_named_event_count":{"type":["integer","null"]},"uncertainty_event_count":{"type":["integer","null"]},"outcome_vintage_count":{"type":["integer","null"]},"operational_event_count":{"type":["integer","null"]},"completeness_status":{"type":"string","enum":["available","empty","unavailable"]},"reason":{"type":"string"}}},"ModelBehaviourRow":{"type":"object","description":"One append-only provider evidence primitive. Missing fields remain null or are represented by an explicit state.","additionalProperties":true},"ModelBehaviourCollection":{"type":"object","required":["version","schema_version","contract_version","resource","filters","rows","next_cursor","terminal"],"properties":{"version":{"type":"string","const":"1"},"schema_version":{"type":"string"},"contract_version":{"type":"string","const":"1.0.0"},"resource":{"type":"string"},"filters":{"type":"object","additionalProperties":true},"rows":{"type":"array","items":{"$ref":"#/components/schemas/ModelBehaviourRow"}},"next_cursor":{"type":["string","null"]},"terminal":{"type":"boolean"},"semantics":{"type":"object","additionalProperties":true}}},"CorpusForecastFamilyCoverage":{"type":"object","required":["model_id","model_name","forecast_channel","forecast_count","censored_forecast_count","matured_forecast_count","authoritative_outcome_count","matched_forecast_count","matured_unmatched_forecast_count","horizon_hours","status","reason"],"properties":{"model_id":{"type":"string","description":"Stable identity of this forecast family."},"model_name":{"type":"string"},"forecast_channel":{"type":"string"},"forecast_count":{"type":"integer","minimum":0},"censored_forecast_count":{"type":"integer","minimum":0},"matured_forecast_count":{"type":"integer","minimum":0},"authoritative_outcome_count":{"type":"integer","minimum":0,"description":"Direct NOAA CRW SST outcomes only; derived and fallback values are excluded."},"matched_forecast_count":{"type":"integer","minimum":0},"matured_unmatched_forecast_count":{"type":"integer","minimum":0,"description":"Matured forecast targets with no same-site CRW outcome within the declared tolerance."},"horizon_hours":{"type":"array","items":{"type":"integer","minimum":0}},"status":{"type":"string","enum":["scoreable","awaiting_outcome","no_match","not_scoreable"]},"reason":{"type":"string","enum":["scoreable_targets_available","targets_pending_observation","matured_targets_without_matching_outcome","no_authoritative_outcome","no_forecast_output","no_forecast_or_outcome"]}}},"CorpusForecastCoverage":{"type":"object","required":["status","reason","model_coverage","outcome_coverage","forecast_count","censored_forecast_count","matured_forecast_count","scoreable_forecast_count","outcome_count","model_ids","required_model_ids","forecast_channels","outcome_channels","families"],"properties":{"status":{"type":"string","enum":["scoreable","awaiting_outcome","no_match","not_scoreable"]},"reason":{"type":"string","enum":["scoreable_targets_available","targets_pending_observation","matured_targets_without_matching_outcome","no_authoritative_outcome","no_forecast_output","no_forecast_or_outcome"]},"model_coverage":{"type":"string","enum":["complete","partial","none"]},"outcome_coverage":{"type":"string","enum":["available","none"]},"forecast_count":{"type":"integer","minimum":0},"censored_forecast_count":{"type":"integer","minimum":0},"matured_forecast_count":{"type":"integer","minimum":0},"scoreable_forecast_count":{"type":"integer","minimum":0},"outcome_count":{"type":"integer","minimum":0},"model_ids":{"type":"array","items":{"type":"string"}},"required_model_ids":{"type":"array","items":{"type":"string"}},"forecast_channels":{"type":"array","items":{"type":"string"}},"outcome_channels":{"type":"array","items":{"type":"string"}},"families":{"type":"array","items":{"$ref":"#/components/schemas/CorpusForecastFamilyCoverage"}},"verification":{"type":"object","description":"Urban verification metrics are withheld until the declared prospective sample window is met.","required":["status","minimum_sample_days","sample_span_days","closed_forecast_count"],"properties":{"status":{"type":"string","enum":["ready","insufficient_history","no_closed_forecasts"]},"minimum_sample_days":{"type":"integer","minimum":1},"sample_span_days":{"type":"integer","minimum":0},"closed_forecast_count":{"type":"integer","minimum":0}}}}},"CorpusEntity":{"type":"object","required":["id","label","lat","lon","tags","domain","first_observation_at","last_observation_at","first_model_valid_at","last_model_valid_at","first_forecast_target_at","last_forecast_target_at","last_available_at","freshness_status","coverage"],"properties":{"id":{"type":"string","example":"air:station:example-id"},"label":{"type":"string"},"lat":{"type":["number","null"]},"lon":{"type":["number","null"]},"tags":{"type":"array","items":{"type":"string"}},"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"first_observation_at":{"type":["string","null"],"format":"date-time"},"last_observation_at":{"type":["string","null"],"format":"date-time"},"first_model_valid_at":{"type":["string","null"],"format":"date-time"},"last_model_valid_at":{"type":["string","null"],"format":"date-time"},"first_forecast_target_at":{"type":["string","null"],"format":"date-time"},"last_forecast_target_at":{"type":["string","null"],"format":"date-time"},"last_available_at":{"type":["string","null"],"format":"date-time"},"freshness_status":{"type":"string","enum":["active","stale","no_data"]},"forecast_entity_id":{"type":["string","null"]},"forecast_entity_relation":{"type":["string","null"],"enum":["direct","mapped",null]},"entity_mapping_version":{"type":["string","null"]},"entity_mapping_method":{"type":["string","null"]},"entity_mapping_confidence":{"type":["number","null"],"minimum":0,"maximum":1},"entity_mapping_is_fallback":{"type":["boolean","null"]},"entity_mapping_fallback":{"type":["string","null"]},"entity_mapping_evidence_id":{"type":["string","null"]},"forecast_coverage":{"$ref":"#/components/schemas/CorpusForecastCoverage"},"coverage":{"type":"object","required":["observed","derived","model_output"],"properties":{"observed":{"type":"boolean"},"derived":{"type":"boolean"},"model_output":{"type":"boolean"}}}}},"CorpusChannelMigration":{"type":"object","required":["legacy_name","replacement_names","status","description"],"properties":{"legacy_name":{"type":"string","description":"Deprecated channel name from an older corpus contract.","example":"model.sst"},"replacement_names":{"type":"array","minItems":1,"items":{"type":"string"},"description":"Canonical channel names to read instead of the legacy name.","example":["model.sst_open_meteo","model.sst_crw_persistence","model.sst_seawatch_lgbm"]},"status":{"type":"string","enum":["deprecated"]},"description":{"type":"string"},"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"],"description":"Present on migrations in the global multi-domain inventory."}}},"CorpusModelFamily":{"type":"object","required":["id","name","role","declared_status","claim_eligible","independence_group","model_ids","channels","scoreable","runtime_status","runtime_reason","last_available_at","evidence"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["forecast","nowcast","projection","surrogate","reference"]},"declared_status":{"type":"string","enum":["supported","experimental"]},"claim_eligible":{"type":"boolean"},"independence_group":{"type":"string"},"model_ids":{"type":"array","items":{"type":"string"}},"channels":{"type":"array","description":"Declared channel names on family metadata; expanded channel contracts on /models.","items":{"oneOf":[{"type":"string"},{"$ref":"#/components/schemas/CorpusChannel"}]}},"scoreable":{"type":"boolean","description":"Climate projections are explicitly not scoreable."},"runtime_status":{"type":"string","enum":["available","stale","unavailable","unknown"]},"runtime_reason":{"type":"string"},"last_available_at":{"type":["string","null"],"format":"date-time"},"unavailable_reason":{"type":"string"},"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"evidence":{"$ref":"#/components/schemas/CorpusModelRuntimeEvidence"}}},"CorpusModelRuntimeEvidence":{"type":"object","additionalProperties":false,"required":["contract_version","assessed_at","basis","reason_code","reason_detail","scope","matched_count","freshness_window_seconds"],"properties":{"contract_version":{"type":"string","enum":["model-family-availability-v1"]},"assessed_at":{"type":"string","format":"date-time"},"basis":{"type":"string","enum":["bounded_persisted_query"]},"reason_code":{"type":"string","enum":["available","stale","no_rows","declaration_only","query_error","invalid_timestamp","no_authoritative_outcome"]},"reason_detail":{"type":"string"},"scope":{"type":"string"},"matched_count":{"type":["integer","null"],"minimum":0},"freshness_window_seconds":{"type":"integer","minimum":0}}},"CorpusModelInventoryEntry":{"allOf":[{"$ref":"#/components/schemas/CorpusModelFamily"},{"type":"object","required":["domain","channels"],"properties":{"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"channels":{"type":"array","items":{"$ref":"#/components/schemas/CorpusChannel"}}}}]},"CorpusTrainerReadiness":{"type":"object","required":["id","domain","trainer","runtime_status","evidence"],"properties":{"id":{"type":"string"},"domain":{"type":"string","enum":["air","sea"]},"trainer":{"type":"string"},"runtime_status":{"type":"string","enum":["available","blocked","unknown"]},"evidence":{"type":"object","required":["reason_code","assessed_at","last_attempt_at","last_success_at","support_count","blocker","next_evidence_threshold"],"properties":{"reason_code":{"type":"string","enum":["trainer_ok","insufficient_evidence","trainer_failed","no_health_receipt","query_error"]},"assessed_at":{"type":"string","format":"date-time"},"last_attempt_at":{"type":["string","null"],"format":"date-time"},"last_success_at":{"type":["string","null"],"format":"date-time"},"support_count":{"type":["integer","null"],"minimum":0},"blocker":{"type":["string","null"]},"next_evidence_threshold":{"type":"string"}}}}},"CorpusTrainingReadiness":{"type":"object","required":["contract_version","assessed_at","basis","domain","posture","reason_code","reason","first_usable_issue_at","first_usable_target_at","latest_usable_issue_at","latest_usable_target_at","forecast_entity_count","forecast_row_count","scoreable_entity_count","scoreable_row_count","observed_entity_count","observed_row_count","authoritative_outcome_available","authoritative_outcome_row_count","claim_eligible_forecast_family_count","model_families","consumer_policy"],"properties":{"contract_version":{"type":"string","const":"training-readiness-v1"},"assessed_at":{"type":"string","format":"date-time"},"basis":{"type":"string","const":"bounded_persisted_aggregates"},"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"posture":{"type":"string","enum":["gated","context","unavailable"]},"reason_code":{"type":"string","enum":["forecast_and_authoritative_outcome_evidence","single_claim_eligible_forecast_family","sparse_context_evidence","no_target_bearing_model_channel","no_usable_forecast_rows","runtime_evidence_unknown"]},"reason":{"type":"string"},"first_usable_issue_at":{"type":["string","null"],"format":"date-time"},"first_usable_target_at":{"type":["string","null"],"format":"date-time"},"latest_usable_issue_at":{"type":["string","null"],"format":"date-time"},"latest_usable_target_at":{"type":["string","null"],"format":"date-time"},"forecast_entity_count":{"type":["integer","null"],"minimum":0},"forecast_row_count":{"type":["integer","null"],"minimum":0},"scoreable_entity_count":{"type":["integer","null"],"minimum":0},"scoreable_row_count":{"type":["integer","null"],"minimum":0},"observed_entity_count":{"type":["integer","null"],"minimum":0},"observed_row_count":{"type":["integer","null"],"minimum":0},"authoritative_outcome_available":{"type":["boolean","null"]},"authoritative_outcome_row_count":{"type":["integer","null"],"minimum":0},"horizons":{"type":"array","description":"Earth-only readiness split by emitted magnitude threshold and forecast horizon; absent for domains without horizon-specific forecast heads.","items":{"type":"object","required":["horizon_hours","threshold","first_usable_issue_at","first_usable_target_at","latest_usable_issue_at","latest_usable_target_at","forecast_entity_count","forecast_row_count","scoreable_entity_count","scoreable_row_count","authoritative_outcome_available"],"properties":{"horizon_hours":{"type":"integer","enum":[24,72,168]},"threshold":{"type":"string","enum":["M4","M5"]},"first_usable_issue_at":{"type":["string","null"],"format":"date-time"},"first_usable_target_at":{"type":["string","null"],"format":"date-time"},"latest_usable_issue_at":{"type":["string","null"],"format":"date-time"},"latest_usable_target_at":{"type":["string","null"],"format":"date-time"},"forecast_entity_count":{"type":"integer","minimum":0},"forecast_row_count":{"type":"integer","minimum":0},"scoreable_entity_count":{"type":"integer","minimum":0},"scoreable_row_count":{"type":"integer","minimum":0},"authoritative_outcome_available":{"type":"boolean"}}}},"claim_eligible_forecast_family_count":{"type":"integer","minimum":0},"model_families":{"type":"array","description":"Only runtime-present or runtime-unknown families are included; absent families are never padded with zero-valued evidence.","items":{"type":"object","required":["id","readiness"],"properties":{"id":{"type":"string"},"readiness":{"type":"object","additionalProperties":true}}}},"consumer_policy":{"type":"object","required":["starts_at_forecast_era","paginate_only_eligible_entities","missing_values_are_absent","promotion_policy_published","promotion_policy"],"properties":{"starts_at_forecast_era":{"type":"boolean","const":true},"paginate_only_eligible_entities":{"type":"boolean","const":true},"missing_values_are_absent":{"type":"boolean","const":true},"promotion_policy_published":{"type":"boolean","const":true},"promotion_policy":{"type":"object","required":["policy_version","minimum_scoreable_rows","requires_authoritative_post_issue_outcomes","requires_empirical_uncertainty_coverage","missing_calibration_fails_closed","family_and_horizon_isolation"],"properties":{"policy_version":{"type":"string","const":"forecast-promotion-v1"},"minimum_scoreable_rows":{"type":"integer","const":300},"requires_authoritative_post_issue_outcomes":{"type":"boolean","const":true},"requires_empirical_uncertainty_coverage":{"type":"boolean","const":true},"missing_calibration_fails_closed":{"type":"boolean","const":true},"family_and_horizon_isolation":{"type":"boolean","const":true}}}}}}},"CorpusModelsResponse":{"type":"object","required":["version","schema_version","generated_at","status","degraded","domains","model_count","models","trainer_readiness","summaries","endpoints"],"properties":{"version":{"type":"string"},"schema_version":{"type":"string"},"generated_at":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["ok","degraded"]},"degraded":{"type":"boolean"},"domains":{"type":"array","items":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}},"model_count":{"type":"integer","minimum":0},"models":{"type":"array","items":{"$ref":"#/components/schemas/CorpusModelInventoryEntry"}},"trainer_readiness":{"type":"array","items":{"$ref":"#/components/schemas/CorpusTrainerReadiness"}},"summaries":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/CorpusModelFamilySummary"}},"endpoints":{"type":"object","additionalProperties":{"type":"string"}}}},"CorpusModelFamilySummary":{"type":"object","required":["declared","runtime_available","independent_forecast","scoreable","nowcast","projection","surrogate","reference","unavailable","reasons"],"properties":{"declared":{"type":"integer","minimum":0},"runtime_available":{"type":"integer","minimum":0},"independent_forecast":{"type":"integer","minimum":0},"scoreable":{"type":"integer","minimum":0},"nowcast":{"type":"integer","minimum":0},"projection":{"type":"integer","minimum":0},"surrogate":{"type":"integer","minimum":0},"reference":{"type":"integer","minimum":0},"unavailable":{"type":"integer","minimum":0},"reasons":{"type":"object","additionalProperties":{"type":"string"}}}},"CorpusChannel":{"type":"object","required":["name","unit","channel_class","log_scale","upstream_provider","upstream_product","native_spatial_resolution","native_temporal_resolution","processing_level","license","redistribution_status","availability_mode","availability_lag_seconds"],"properties":{"name":{"type":"string","description":"Canonical machine-readable channel name."},"unit":{"type":"string"},"channel_class":{"type":"string","enum":["observed","derived","model_output"]},"log_scale":{"type":"boolean"},"upstream_provider":{"type":"string"},"upstream_product":{"type":"string"},"native_spatial_resolution":{"type":"string"},"native_temporal_resolution":{"type":"string"},"processing_level":{"type":"string","enum":["raw","aggregated","derived","modelled"]},"license":{"type":"string"},"redistribution_status":{"type":"string","enum":["allowed_with_attribution","source_specific","restricted_non_commercial"]},"availability_mode":{"type":"string","enum":["publication_time","ingest_time"]},"availability_lag_seconds":{"type":"number","minimum":0},"availability_description":{"type":"string"},"model_id":{"type":"string","minLength":1},"model_name":{"type":"string"},"model_version":{"type":"string","minLength":1},"model_family":{"type":"string"},"model_method":{"type":"string"},"model_inputs":{"type":"array","items":{"type":"string"}},"uncertainty_type":{"type":"string","enum":["interval","quantiles","none"]},"uncertainty_kind":{"type":"string","enum":["interval","quantiles","none"],"description":"Explicit uncertainty representation; mirrors uncertainty_type."},"uncertainty_description":{"type":"string"},"uncertainty_coverage":{"type":"number","minimum":0,"maximum":1,"description":"Nominal central coverage for interval or quantile uncertainty."},"forecast_head_id":{"type":"string","minLength":1,"description":"Stable identity for one predicted quantity across supported horizons. A row-level head instance is this ID joined with entity_id, available_at, timestamp, prediction_horizon_seconds, model_family, and model_version."},"uncertainty_role":{"type":"string","enum":["point","lower","upper"],"description":"This channel's role within a machine-readable uncertainty companion set."},"uncertainty_point_channel":{"type":"string","minLength":1,"description":"Canonical point-estimate channel for this forecast head."},"uncertainty_lower_channel":{"type":"string","minLength":1,"description":"Canonical lower-bound channel when an interval is actually published. Absence never implies a zero-width interval."},"uncertainty_upper_channel":{"type":"string","minLength":1,"description":"Canonical upper-bound channel when an interval is actually published. Absence never implies a zero-width interval."},"claim_status":{"type":"string","enum":["supported","provisional","not_claimed"],"description":"Channel-level claim posture. Training evidence weights never determine this field."},"training_evidence":{"type":"object","required":["policy_version","constants_hash","evaluation_mode","evidence_law","promotion_effect","axes","description"],"properties":{"policy_version":{"type":"string","example":"evidence-profiles-v1"},"constants_hash":{"type":"string","example":"74d08d1dd0962dd4","description":"Truncated SHA-256 of the separately versioned evidence policy constants."},"evaluation_mode":{"type":"string","enum":["diagnostic_only"]},"evidence_law":{"type":"string","enum":["claim-isolated","pooled-experimental"]},"promotion_effect":{"type":"string","enum":["none"]},"axes":{"type":"array","uniqueItems":true,"items":{"type":"string","enum":["temporal","lineage","independence","uncertainty","freshness"]}},"description":{"type":"string"}},"description":"Diagnostic training-evidence metadata. It is separate from claim validity, uncertainty calibration, freshness, and row lineage."},"prediction_horizon":{"type":"string"},"temporal_role":{"type":"string","enum":["observation","nowcast","forecast","projection"]},"prediction_horizon_seconds":{"type":"integer","minimum":0,"description":"Present only for a genuinely fixed-lead channel. Every model-output row also carries its exact lead."},"prediction_horizon_mode":{"type":"string","enum":["fixed","range","supported_set","row_exact"]},"prediction_horizon_min_seconds":{"type":"integer","minimum":0},"prediction_horizon_max_seconds":{"type":"integer","minimum":0},"prediction_horizon_values_seconds":{"type":"array","minItems":1,"uniqueItems":true,"items":{"type":"integer","minimum":0}},"score_against":{"type":"string"},"score_alignment":{"type":"string","enum":["exact_target","nearest_within_window"]},"score_tolerance_seconds":{"type":"number","minimum":0},"score_join_keys":{"type":"array","items":{"type":"string"}},"score_episode_keys":{"type":"array","items":{"type":"string"}},"score_outcome_requirements":{"type":"array","items":{"type":"string"}},"independence_condition":{"type":"string"},"description":{"type":"string"}},"allOf":[{"if":{"properties":{"channel_class":{"const":"model_output"}}},"then":{"required":["model_id","model_version","model_family","model_method","model_inputs","uncertainty_type","uncertainty_description","prediction_horizon_mode"]}},{"if":{"properties":{"channel_class":{"const":"model_output"},"uncertainty_type":{"enum":["interval","quantiles"]}},"required":["channel_class","uncertainty_type"]},"then":{"required":["uncertainty_coverage"]}},{"if":{"properties":{"prediction_horizon_mode":{"const":"fixed"}},"required":["prediction_horizon_mode"]},"then":{"required":["prediction_horizon_seconds"]}},{"if":{"properties":{"prediction_horizon_mode":{"const":"range"}},"required":["prediction_horizon_mode"]},"then":{"required":["prediction_horizon_min_seconds","prediction_horizon_max_seconds"]}},{"if":{"properties":{"prediction_horizon_mode":{"const":"supported_set"}},"required":["prediction_horizon_mode"]},"then":{"required":["prediction_horizon_min_seconds","prediction_horizon_max_seconds","prediction_horizon_values_seconds"]}}]},"CorpusHistorySummary":{"type":"object","required":["start_at","end_at","archive_depth_days","finalized_through","finalized_days","coverage_semantics"],"properties":{"start_at":{"type":["string","null"],"format":"date-time"},"end_at":{"type":["string","null"],"format":"date-time"},"archive_depth_days":{"type":"integer","minimum":0},"finalized_through":{"type":["string","null"],"format":"date-time"},"finalized_days":{"type":"integer","minimum":0},"coverage_semantics":{"type":"string","enum":["observed_calendar_span","cross_domain_envelope"],"description":"Per-domain depth is the inclusive calendar span of retained observations. The global response uses cross_domain_envelope and makes no archive-depth or finalization claim."}}},"CorpusObservation":{"type":"object","required":["observation_id","entity_id","record_class","temporal_role","timestamp","available_at","values","sources","source_count","revision","revision_of","lineage"],"allOf":[{"if":{"properties":{"record_class":{"const":"model_output"}}},"then":{"required":["model_id","model_version","model_family","model_method","model_inputs"]}}],"properties":{"observation_id":{"type":"string","description":"Stable entity-qualified row identifier."},"entity_id":{"type":"string","description":"Stable public entity ID this row belongs to."},"record_class":{"type":"string","enum":["observed","derived","model_output"]},"temporal_role":{"type":"string","enum":["observation","nowcast","forecast","projection"]},"timestamp":{"type":"string","format":"date-time","description":"Observation or forecast valid time."},"available_at":{"type":"string","format":"date-time","description":"Publication, computation, or model issue time."},"ingested_at":{"type":["string","null"],"format":"date-time"},"values":{"type":"object","additionalProperties":{"type":"number"}},"sources":{"type":"array","items":{"type":"string"}},"source_count":{"type":"integer","minimum":0},"revision":{"type":"integer","minimum":1},"revision_of":{"type":["string","null"]},"model_id":{"type":"string","minLength":1,"description":"Stable non-generic public model identifier."},"model_name":{"type":"string"},"model_version":{"type":"string","minLength":1,"description":"Immutable semantic model version; never an execution or training run ID."},"model_run_id":{"type":"string","description":"Dynamic model execution, training, or upstream run provenance."},"model_family":{"type":"string"},"model_method":{"type":"string"},"model_inputs":{"type":"array","items":{"type":"string"}},"independence_reference_model_id":{"type":"string"},"independence_reference_model_run_id":{"type":"string"},"independence_basis":{"type":"string"},"issued_entity_id":{"type":"string"},"issued_entity_kind":{"type":"string"},"entity_attribution":{"type":"string","enum":["direct","mapped"]},"entity_mapping_version":{"type":"string"},"entity_mapping_method":{"type":"string"},"entity_mapping_confidence":{"type":"number","minimum":0,"maximum":1},"entity_mapping_fallback":{"type":"boolean","description":"True only for a non-authoritative fallback attribution. Default corpus scoring excludes these outcomes."},"entity_mapping_evidence_ids":{"type":"array","items":{"type":"string"},"description":"Stable station-to-ward mapping evidence identities used to construct this outcome."},"prediction_horizon_seconds":{"type":"integer","minimum":0},"lineage":{"type":"object","additionalProperties":true}}},"CorpusForecastVintage":{"type":"object","description":"Legacy immutable verification receipt. run_at is unavailable and available_at is the outcome publication clock; use forecast-events for distinct forecast emission/publication timing.","required":["vintage_id","domain","entity_id","model_family","model_version","forecast_run_id","issued_at","run_at","available_at","target_at","outcome_observed_at","outcome_available_at","revision","revision_of","forecast_value","outcome_value","unit","value_semantics","transformation","forecast_ref","outcome_ref","verified_at"],"properties":{"vintage_id":{"type":"string"},"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"entity_id":{"type":"string"},"model_family":{"type":"string"},"model_version":{"type":"string"},"forecast_run_id":{"type":"string"},"issued_at":{"type":"string","format":"date-time"},"run_at":{"type":["string","null"],"format":"date-time","description":"Unavailable in the compatibility store; currently always null."},"available_at":{"type":["string","null"],"format":"date-time","description":"Compatibility alias of outcome_available_at, not a separate forecast publication clock."},"target_at":{"type":"string","format":"date-time"},"outcome_observed_at":{"type":"string","format":"date-time"},"outcome_available_at":{"type":"string","format":"date-time"},"revision":{"type":"integer","minimum":1},"revision_of":{"type":["string","null"]},"forecast_value":{"type":"number"},"outcome_value":{"type":"number"},"unit":{"type":"string"},"value_semantics":{"type":"string","const":"persisted_forecast_value"},"transformation":{"type":["object","null"],"additionalProperties":true},"forecast_ref":{"type":"string"},"outcome_ref":{"type":"string"},"verified_at":{"type":"string","format":"date-time"}}},"CorpusForecastVintagesResponse":{"type":"object","required":["version","schema_version","generated_at","filters","vintages","next_cursor","terminal","semantics"],"properties":{"version":{"type":"string"},"schema_version":{"type":"string"},"generated_at":{"type":"string","format":"date-time"},"filters":{"type":"object","additionalProperties":true},"vintages":{"type":"array","items":{"$ref":"#/components/schemas/CorpusForecastVintage"}},"next_cursor":{"type":["string","null"]},"terminal":{"type":"boolean"},"semantics":{"type":"object","additionalProperties":{"type":"string"}}}},"CorpusEvaluationRow":{"type":"object","required":["domain","model_family","model_version","unit","sample_count","mae","bias","rmse","interval_coverage","interval_width","brier_score","log_score","scoring_window","outcome_lineage","metric_availability"],"properties":{"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"model_family":{"type":"string"},"model_version":{"type":"string"},"unit":{"type":"string"},"sample_count":{"type":"integer","minimum":0},"mae":{"type":"number"},"bias":{"type":"number"},"rmse":{"type":"number"},"interval_coverage":{"type":["number","null"],"minimum":0,"maximum":1},"interval_width":{"type":["number","null"],"minimum":0},"brier_score":{"type":["number","null"],"minimum":0},"log_score":{"type":["number","null"]},"scoring_window":{"type":"object","additionalProperties":true},"outcome_lineage":{"type":"object","additionalProperties":true},"metric_availability":{"type":"object","additionalProperties":{"type":"string"}}}},"CorpusEvaluationResponse":{"type":"object","required":["version","schema_version","generated_at","filters","evaluation","semantics","denominators","matching_rules"],"properties":{"version":{"type":"string"},"schema_version":{"type":"string"},"generated_at":{"type":"string","format":"date-time"},"filters":{"type":"object","additionalProperties":true},"evaluation":{"type":"array","items":{"$ref":"#/components/schemas/CorpusEvaluationRow"}},"semantics":{"type":"object","additionalProperties":{"type":"string"}},"denominators":{"type":"object","description":"Population indicators with different scopes. verified_intersection_count is the matched evaluation sample total. Forecast-ledger and outcome-vintage counts do not all inherit the target-time, family, or model-version filters; do not treat them as one common scorecard denominator.","required":["forecast_event_count","outcome_vintage_count","uncertainty_event_count","peer_named_event_count","verified_intersection_count","outcome_vintage_completeness","uncertainty_coverage","peer_completeness","version_continuity","prospective"],"properties":{"forecast_event_count":{"type":"integer","minimum":0},"outcome_vintage_count":{"type":"integer","minimum":0},"uncertainty_event_count":{"type":"integer","minimum":0},"peer_named_event_count":{"type":"integer","minimum":0},"verified_intersection_count":{"type":"integer","minimum":0},"outcome_vintage_completeness":{"type":"string","enum":["observed","unknown"],"description":"Presence signal only: observed means at least one outcome vintage matched the outcome query filters, not that a target window is complete or final."},"uncertainty_coverage":{"type":["number","null"],"minimum":0,"maximum":1},"peer_completeness":{"type":["number","null"],"minimum":0,"maximum":1},"version_continuity":{"type":"string","enum":["observed","unknown"],"description":"Currently unknown; inspect lifecycle events for continuity evidence."},"prospective":{"type":"object","required":["scope","by_domain","totals","matching"],"properties":{"scope":{"type":"string"},"matching":{"type":"string"},"by_domain":{"type":"array","items":{"type":"object","required":["domain","forecast_event_count","emitted_event_count","abstained_event_count","outcome_vintage_count","verified_intersection_count"],"properties":{"domain":{"type":"string"},"forecast_event_count":{"type":"integer","minimum":0},"emitted_event_count":{"type":"integer","minimum":0},"abstained_event_count":{"type":"integer","minimum":0},"outcome_vintage_count":{"type":"integer","minimum":0},"verified_intersection_count":{"type":"integer","minimum":0}}}},"totals":{"type":"object","required":["forecast_event_count","emitted_event_count","abstained_event_count","outcome_vintage_count","verified_intersection_count"],"additionalProperties":false,"properties":{"forecast_event_count":{"type":"integer","minimum":0},"emitted_event_count":{"type":"integer","minimum":0},"abstained_event_count":{"type":"integer","minimum":0},"outcome_vintage_count":{"type":"integer","minimum":0},"verified_intersection_count":{"type":"integer","minimum":0}}}}}}},"matching_rules":{"type":"object","additionalProperties":{"type":"string"}}}},"CompoundRiskEventV1":{"type":"object","required":["id","schema_version","risk_type","primary_domain","secondary_domain","description","severity","active","started_at","affected_regions","evidence_ids","combination_methodology","confidence","limitations","fingerprint"],"properties":{"id":{"type":"integer"},"schema_version":{"type":"string","example":"1.0.0"},"risk_type":{"type":"string","description":"Detector pattern identifier.","example":"fire_smoke_intrusion","enum":["fire_smoke_intrusion","flood_seismic_liquefaction","drought_fire_escalation","marine_heat_ecological_screening","heat_ozone_photochem","flood_crop_inundation"]},"primary_domain":{"type":"string","example":"air"},"secondary_domain":{"type":"string","example":"agro"},"description":{"type":"string"},"severity":{"type":"string","enum":["advisory","watch","warning"]},"active":{"type":"boolean"},"started_at":{"type":"string","format":"date-time","nullable":true},"expires_at":{"type":"string","format":"date-time","nullable":true},"resolved_at":{"type":"string","format":"date-time","nullable":true},"affected_regions":{"type":"object","description":"Domain-specific geographic context for this event. Schema varies by risk_type."},"evidence":{"type":"object","description":"Raw per-pattern signal data (thresholds crossed, reading counts, etc.). Schema varies by risk_type. Internal combination-metadata keys are stripped from this object."},"evidence_ids":{"type":"array","items":{"type":"string"},"description":"Stable `urn:evidence:<domain>:<entityKey>:<date>` UUID-v5 identifiers for each domain signal that triggered this event. Empty for events persisted before evidence-linked metadata was available (see `combination_methodology.slug: 'legacy_unstructured'`).","example":["urn:evidence:air:delhi-ncr-pm25:2026-07-30"]},"combination_methodology":{"type":"object","required":["slug","description"],"properties":{"slug":{"type":"string","description":"Machine-readable join strategy. Stable across detector runs.","example":"threshold_join_fires_24h_wind_6h_pm25_6h"},"description":{"type":"string","description":"Human-readable description of the join logic used to detect this compound event."}}},"time_alignment":{"type":"object","nullable":true,"required":["window_hours","oldest_contributing_at","newest_contributing_at"],"properties":{"window_hours":{"type":"number","description":"Total look-back window all contributing signals fall within."},"oldest_contributing_at":{"type":"string","format":"date-time"},"newest_contributing_at":{"type":"string","format":"date-time"}}},"spatial_alignment":{"type":"object","nullable":true,"required":["method"],"properties":{"method":{"type":"string","enum":["centroid_distance","bbox_intersect","ward_boundary"],"description":"Geometric method used to join contributing signals across domains."},"max_distance_km":{"type":"number","nullable":true,"description":"Maximum join radius in km (only meaningful for centroid_distance)."}}},"confidence":{"type":"object","required":["level","basis","missing_inputs"],"properties":{"level":{"type":"string","enum":["high","moderate","low"],"description":"Overall confidence in this compound event. `low` is also returned as a safe fallback for legacy events."},"basis":{"type":"string","description":"Human-readable explanation of why this confidence level was assigned."},"missing_inputs":{"type":"array","items":{"type":"string"},"description":"Named signals that were unavailable or below the quality threshold at detection time. Agents should check this before acting on the event."}}},"limitations":{"type":"array","items":{"type":"string"},"description":"Known caveats about data quality or inference gaps for this specific event type."},"fingerprint":{"type":"string","description":"Stable deduplication key (`<risk_type>:<date>`). Use to correlate the same event across polling calls.","example":"fire_smoke_intrusion:2026-07-30"}}},"SatelliteTaskingRequestStatus":{"type":"object","required":["request_id","status","submitted_at","review_eta_hours","domain","purpose","observation_window","requested_by_asset_ids"],"properties":{"request_id":{"type":"string","format":"uuid","description":"Stable opaque ID for this request. Use to poll status."},"status":{"type":"string","enum":["pending_review","approved","rejected","fulfilled"],"description":"`pending_review` = awaiting human review; `approved` = operator approved, acquisition being scheduled; `rejected` = operator declined (see reviewer_note); `fulfilled` = acquisition complete, scene ingested into /v1/satellite/scenes."},"submitted_at":{"type":"string","format":"date-time"},"reviewed_at":{"type":"string","format":"date-time","nullable":true},"reviewer_note":{"type":"string","nullable":true,"description":"Human-readable note from the reviewing operator. Populated on approval or rejection."},"review_eta_hours":{"type":"integer","description":"Estimated hours until the initial review decision. Informational only — not a guarantee.","example":48},"domain":{"type":"string","enum":["air","urban","agriculture","sea"]},"purpose":{"type":"string"},"observation_window":{"type":"object","properties":{"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"}}},"requested_by_asset_ids":{"type":"array","items":{"type":"string"},"description":"Caller-supplied asset IDs echoed back from the submission."},"message":{"type":"string","nullable":true,"description":"Human-readable guidance for next steps (present on POST response only)."}}},"AuthError":{"type":"object","required":["error","message"],"properties":{"error":{"type":"string","example":"missing_api_key","description":"Machine-readable error code. One of: `missing_api_key`, `invalid_api_key`, `revoked_api_key`."},"message":{"type":"string","example":"No API key provided."},"signUpUrl":{"type":"string","example":"https://airdelhi.net/developers","description":"URL where the caller can obtain a key."}}},"QuotaError":{"type":"object","required":["error","message"],"properties":{"error":{"type":"string","example":"quota_exceeded"},"message":{"type":"string","example":"Monthly quota of 1000 requests exhausted. Resets at 2024-11-01T00:00:00.000Z."},"resetAt":{"type":"string","format":"date-time","description":"ISO-8601 timestamp when the quota resets."}}},"ApiError":{"type":"object","required":["data","meta","error"],"properties":{"data":{"nullable":true,"example":null},"meta":{"type":"object","required":["generated_at"],"properties":{"generated_at":{"type":"string","format":"date-time","example":"2024-10-15T06:30:00.000Z"}}},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"ward_not_found"},"message":{"type":"string","example":"No ward found with id 'INVALID'."}}}}},"AqiTier":{"type":"string","enum":["good","satisfactory","moderate","poor","very_poor","severe"],"description":"India NAQI AQI category."},"ApiTier":{"type":"string","enum":["free","pro","enterprise"],"description":"API access tier (legacy — all endpoints are free for all keys)."},"WardSummary":{"type":"object","properties":{"ward_id":{"type":"string","example":"W-042","description":"Unique ward identifier."},"name":{"type":"string","example":"Karol Bagh"},"district":{"type":"string","example":"Central Delhi"},"lat":{"type":"number","format":"float","example":28.651},"lon":{"type":"number","format":"float","example":77.189},"current":{"nullable":true,"type":"object","properties":{"pm25":{"type":"number","format":"float","example":87.4,"description":"IDW-interpolated PM2.5 in µg/m³."},"unit":{"type":"string","example":"µg/m³"},"tier":{"$ref":"#/components/schemas/AqiTier"},"measured_at":{"type":"string","format":"date-time","example":"2024-10-15T06:00:00.000Z"},"source":{"type":"string","enum":["live","estimated"],"description":"`live` = a ground monitor is within 2 km; `estimated` = IDW-interpolated from more distant stations."}}}}},"ForecastPoint":{"type":"object","properties":{"target_at":{"type":"string","format":"date-time","example":"2024-10-15T09:00:00.000Z"},"horizon_hours":{"type":"integer","example":3,"description":"Hours from forecast issuance to this point."},"point":{"type":"number","format":"float","example":92.1,"description":"Point estimate in µg/m³."},"lower_90":{"type":"number","format":"float","example":74.5,"description":"90 % prediction interval lower bound."},"upper_90":{"type":"number","format":"float","example":113.8,"description":"90 % prediction interval upper bound."},"tier":{"$ref":"#/components/schemas/AqiTier"},"confidence":{"type":"string","enum":["high","medium","low"],"description":"Qualitative confidence: `high` = tight interval (< 30 % of point), `medium` = moderate, `low` = wide interval or zero point."}}},"VentilationWindow":{"type":"object","properties":{"start_at":{"type":"string","format":"date-time","example":"2024-10-15T05:00:00.000Z"},"end_at":{"type":"string","format":"date-time","example":"2024-10-15T09:00:00.000Z"},"duration_hours":{"type":"integer","example":4},"mean_pm25":{"type":"number","format":"float","example":28.3},"peak_pm25":{"type":"number","format":"float","example":32.1},"tier":{"$ref":"#/components/schemas/AqiTier"}}},"HourPoint":{"type":"object","description":"One forecast hour in the scanned window.","properties":{"time":{"type":"string","format":"date-time"},"pm25":{"type":"number","format":"float"},"pm25_low":{"type":"number","format":"float"},"pm25_high":{"type":"number","format":"float"},"tier":{"$ref":"#/components/schemas/AqiTier"},"below_threshold":{"type":"boolean"}}},"GlobalSourceCatalogResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","required":["source","provider_name","documentation_url","license_url","access_mode","operational_readiness"],"properties":{"source":{"type":"string"},"provider_name":{"type":"string"},"documentation_url":{"type":"string","format":"uri"},"license_url":{"type":"string","format":"uri"},"access_mode":{"type":"string","enum":["anonymous_public","key_required","signup_required"]},"refresh_expectation":{"type":"string"},"coverage":{"type":"string"},"provenance_policy":{"type":"string"},"operational_readiness":{"type":"string","enum":["ready","periodic","unavailable","deferred"]},"checked_at":{"type":"string","format":"date-time"},"endpoint":{"type":"string","format":"uri"},"notes":{"type":"string"},"health":{"type":"object","additionalProperties":true}}}},"training_policy":{"type":"object","description":"Resource-aware training order and fail-closed activation gates for contextual Global Context inputs.","additionalProperties":true},"meta":{"type":"object","additionalProperties":true}}},"GlobalHealthResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","required":["source","status"],"properties":{"source":{"type":"string"},"status":{"type":"string"},"last_attempt_at":{"type":["string","null"],"format":"date-time"},"last_usable_output_at":{"type":["string","null"],"format":"date-time"},"last_error_at":{"type":["string","null"],"format":"date-time"},"freshness_seconds":{"type":["number","null"]},"consecutive_failures":{"type":"integer"},"failure_class":{"type":["string","null"]},"note":{"type":["string","null"]},"operations":{"type":"object","additionalProperties":true,"description":"Transport, parse, usable-record, coverage, cache, stale-on-error, and resume facts."}}}},"meta":{"type":"object","additionalProperties":true}}},"GlobalSignalsResponse":{"type":"object","required":["data","pagination","meta"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","source","domain","record_type","source_record_id","retrieved_at","quality_flags","evidence"],"additionalProperties":true,"properties":{"id":{"type":"integer"},"source":{"type":"string"},"domain":{"type":"string"},"record_type":{"type":"string"},"source_record_id":{"type":"string"},"retrieved_at":{"type":"string","format":"date-time"},"quality_flags":{"type":"array","items":{"type":"string"}},"evidence":{"type":"object"}}}},"pagination":{"type":"object","required":["limit","returned","has_next_page","next_cursor"],"properties":{"limit":{"type":"integer"},"returned":{"type":"integer"},"has_next_page":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}},"meta":{"type":"object","additionalProperties":true}}}}},"paths":{"/v1/forecasts/capabilities":{"get":{"operationId":"getAgentForecastCapabilities","tags":["agent-forecasts"],"summary":"Read agent forecast lifecycle limits and evidence qualification","description":"Requires a user-owned API key with forecast:read. Reports the currently supported Air PM2.5 lane and explicitly unavailable qualification or settlement states.","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Lifecycle capabilities and current evidence gates."}}}},"/v1/forecasts":{"get":{"operationId":"listAgentForecasts","tags":["agent-forecasts"],"summary":"List forecasts owned by the API key's human account","description":"Records are private to the Clerk user linked to the API key. Ownerless and strategic-partner credentials are not accepted.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Owner-scoped forecasts."},"403":{"description":"API key has no linked human owner or lacks forecast:read."}}},"post":{"operationId":"createAgentForecast","tags":["agent-forecasts"],"summary":"Issue an owner-scoped Air PM2.5 forecast","description":"Requires forecast:write and Idempotency-Key. Distribution must explicitly be unavailable until calibration is qualified. Source independence remains unknown unless supported by linked evidence.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain","entityId","claim","targetAt","outcomeContract","distribution","sourceIds","actionStatement"],"properties":{"domain":{"type":"string","const":"air"},"entityId":{"type":"string","pattern":"^air:ward:[A-Za-z0-9_-]{1,80}$"},"claim":{"type":"string","minLength":8,"maxLength":600},"targetAt":{"type":"string","format":"date-time"},"outcomeContract":{"type":"object","required":["quantity","comparator","threshold","unit"],"properties":{"quantity":{"type":"string","const":"PM2.5 concentration"},"comparator":{"type":"string","enum":["gt","gte","lt","lte"]},"threshold":{"type":"number","minimum":0,"maximum":1000},"unit":{"type":"string","const":"ug/m3"}},"additionalProperties":false},"distribution":{"type":"object","required":["status","reason"],"properties":{"status":{"type":"string","const":"unavailable"},"reason":{"type":"string","minLength":1,"maxLength":500}},"additionalProperties":false},"sourceIds":{"type":"array","minItems":1,"maxItems":5,"items":{"type":"string","enum":["airnow","cpcb","openaq","purpleair","us-embassy"]}},"evidenceRefs":{"type":"array","maxItems":20,"items":{"type":"string"}},"actionStatement":{"type":"string","minLength":1,"maxLength":1500}},"additionalProperties":false}}}},"responses":{"201":{"description":"Forecast issued and immutable issue event retained."},"400":{"description":"Invalid forecast contract."},"403":{"description":"API key lacks forecast:write or has no human owner."}}}},"/v1/forecasts/{forecastId}":{"get":{"operationId":"getAgentForecast","tags":["agent-forecasts"],"summary":"Read an owned forecast and its lifecycle history","description":"Returns the current owner-scoped projection and verifies the retained event hash chain before returning lifecycle history.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"forecastId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Forecast snapshot and hash-linked event history."},"404":{"description":"Forecast not found for this owner."}}}},"/v1/forecasts/{forecastId}/updates":{"post":{"operationId":"appendAgentForecastUpdate","tags":["agent-forecasts"],"summary":"Append a forecast revision","description":"Revisions do not replace the issue-time snapshot or any prior event.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"forecastId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"distribution":{"type":"object","required":["status","reason"],"properties":{"status":{"type":"string","const":"unavailable"},"reason":{"type":"string"}},"additionalProperties":false},"evidenceRefs":{"type":"array","maxItems":20,"items":{"type":"string"}},"actionStatement":{"type":"string","maxLength":1500}},"additionalProperties":false}}}},"responses":{"200":{"description":"New revision appended."},"409":{"description":"Forecast is no longer open."}}}},"/v1/forecasts/{forecastId}/transfer":{"post":{"operationId":"requestAgentForecastTransfer","tags":["agent-forecasts"],"summary":"Request transfer to another account","description":"The current human owner must approve or veto in the signed-in owner view before ownership changes.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"forecastId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["targetOwnerUserId"],"properties":{"targetOwnerUserId":{"type":"string","minLength":5,"maxLength":120}},"additionalProperties":false}}}},"responses":{"202":{"description":"Transfer awaiting human decision."},"409":{"description":"Transfer already pending or target is invalid."}}}},"/v1/forecasts/{forecastId}/retire":{"post":{"operationId":"retireAgentForecast","tags":["agent-forecasts"],"summary":"Retire a forecast without deleting its history","description":"Stops an active watch and appends a retirement event; prior issue and update records remain immutable.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"forecastId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":500}},"additionalProperties":false}}}},"responses":{"200":{"description":"Forecast retired and watch stopped."},"409":{"description":"Forecast already retired."}}}},"/v1/forecasts/{forecastId}/resolve":{"post":{"operationId":"resolveAgentForecast","tags":["agent-forecasts"],"summary":"Resolve from a later exact-match outcome receipt","description":"Requires a final, later Air PM2.5 corpus outcome vintage matching the exact ward, target timestamp, declared source, and receipt contract. Stale, reconstructed, or mismatched evidence is rejected.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"forecastId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["outcomeVintageId"],"properties":{"outcomeVintageId":{"type":"string","minLength":1,"maxLength":220}},"additionalProperties":false}}}},"responses":{"200":{"description":"Forecast resolved with the exact outcome receipt."},"409":{"description":"Outcome receipt does not pass the exact eligibility gate."}}}},"/v1/forecasts/{forecastId}/watch":{"post":{"operationId":"setAgentForecastWatch","tags":["agent-forecasts"],"summary":"Enable or stop a bounded outcome watch","description":"At most 25 due forecasts are checked per sweep and 100 exact-target outcome receipts are inspected per forecast. Missing or ineligible evidence is recorded as unresolved.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"forecastId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Watch state appended."}}}},"/v1/forecasts/{forecastId}/stake-intents":{"post":{"operationId":"recordAgentForecastStakeIntent","tags":["agent-forecasts"],"summary":"Record a typed stake intent without settlement","description":"If no verified settlement contract exists, the intent is explicitly unavailable. No balance is simulated and no funds are moved.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"forecastId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["intentType","amountMinor","asset"],"properties":{"intentType":{"type":"string","const":"prediction-stake"},"amountMinor":{"type":"integer","minimum":1,"maximum":1000000000},"asset":{"type":"string","pattern":"^[A-Z][A-Z0-9]{1,11}$"},"note":{"type":"string","maxLength":500}},"additionalProperties":false}}}},"responses":{"202":{"description":"Intent recorded; settlement remains unavailable and was not attempted."}}}},"/v1/developer-inventory":{"get":{"operationId":"getDeveloperInventory","tags":["Capabilities"],"summary":"Generated public and partner API inventory","description":"Reconciles every served OpenAPI operation with its access class and direct /api alias. Internal, admin, webhook, and owner key-management surfaces are listed separately as intentional exclusions.","security":[],"responses":{"200":{"description":"Generated developer inventory and exclusions."}}}},"/v1/place-evidence/capabilities":{"get":{"operationId":"getPlaceEvidenceCapabilities","tags":["Place evidence"],"summary":"Discover the bounded place-evidence contract","description":"Publicly declares supported place families, bounds, retention, and place-evidence-eligibility/v2. Comparisons require the same mapped place, task, native unit, exact target time, declared lead class, and an outcome available after issue; fractional horizons remain audit fields.","security":[],"responses":{"200":{"description":"Place-evidence capabilities.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/v1/place-evidence/example":{"get":{"operationId":"getPlaceEvidenceExample","tags":["Place evidence"],"summary":"Retrieve the retained public place-evidence example","description":"Returns the scheduler-retained qualified example without recomputing or persisting candidates on request. Follow its citation URL for exact replay; truncated verification is partial and cannot qualify.","security":[],"responses":{"200":{"description":"Retained place-evidence package.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"503":{"description":"No qualified retained example is available."}}}},"/v1/place-evidence":{"post":{"operationId":"createPlaceEvidence","tags":["Place evidence"],"summary":"Construct a bounded place-evidence package","description":"Public bounded retrieval for a source-native package with separate at-decision and after-verification clocks. place-evidence-eligibility/v2 pairs by declared lead class, preserves exact fractional horizons, and reports bounded verification as partial.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["place_id","from","to"],"properties":{"place_id":{"type":"string","minLength":1,"maxLength":180},"domain":{"type":"string","enum":["air","agriculture","sea","urban"]},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Bounded place-evidence package.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid place or time range."},"503":{"description":"Evidence construction is temporarily unavailable."}}}},"/v1/place-evidence/query":{"post":{"operationId":"queryPlaceEvidence","tags":["Place evidence"],"summary":"Construct a bounded place-evidence package","description":"Alias for POST /v1/place-evidence.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/paths/~1v1~1place-evidence/post/requestBody/content~1application~1json/schema"}}}},"responses":{"200":{"description":"Bounded place-evidence package.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid place or time range."},"503":{"description":"Evidence construction is temporarily unavailable."}}}},"/v1/place-evidence/citations/{citation_id}":{"get":{"operationId":"replayPlaceEvidenceCitation","tags":["Place evidence"],"summary":"Replay a retained place-evidence citation","description":"Replays the retained package and never queries current data. An expired citation returns 410.","security":[],"parameters":[{"name":"citation_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":180}}],"responses":{"200":{"description":"Retained place-evidence package with replay=true.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"404":{"description":"Citation not found."},"410":{"description":"Citation expired."}}}},"/v1/worldlines":{"get":{"tags":["Worldline"],"operationId":"discoverWorldlineProtocol","summary":"Discover Worldline domains, stages, signal classes, and budgets","description":"Publicly declares the Worldline domains, knowledge stages, signal classes, query budgets, retention, and links needed before constructing a bounded graph.","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Worldline protocol discovery.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}},"post":{"tags":["Worldline"],"operationId":"constructWorldline","summary":"Construct a bounded, reproducible Worldline graph","description":"Projects existing State Layers and persisted evidence into a typed graph. Requires an API key because Global Context and model lifecycle records retain their existing access boundary. Missing, stale, unavailable, restricted, and partial states remain explicit; no causal claims are emitted.","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["geometry","from","to","domains"],"properties":{"geometry":{"type":"object","description":"BBox, Circle, or Polygon geometry."},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"domains":{"type":"array","minItems":1,"maxItems":6,"items":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}},"stages":{"type":"array","items":{"type":"string"}},"signal_classes":{"type":"array","items":{"type":"string"}},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":200},"cursor":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"Worldline page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorldlineResponse"}}}},"400":{"description":"Invalid bounds, filters, or continuation cursor."},"410":{"description":"The cited continuation snapshot has expired."},"503":{"description":"Unavailable Worldline; no empty success is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorldlineUnavailableResponse"}}}}}}},"/world/v1/worldlines/capabilities":{"get":{"tags":["Worldline"],"operationId":"discoverPublicWorldlineProtocol","summary":"Public Worldline protocol discovery","description":"Publicly declares the Worldline domains, stages, signal classes, budgets, rights boundary, and query links without exposing evidence rows.","security":[],"responses":{"200":{"description":"Worldline protocol discovery.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/v1/worldlines/citations/{citation_id}":{"get":{"tags":["Worldline"],"operationId":"retrieveWorldlineCitation","summary":"Retrieve the exact retained Worldline snapshot","description":"Replays the exact retained graph identified by citation_id, including its content hash, source rights, warnings, gaps, and retention boundary.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"citation_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Exact retained graph snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorldlineResponse"}}}},"404":{"description":"Citation not found or expired."}}}},"/world/v1/layers":{"get":{"tags":["WorldState"],"operationId":"listStateLayers","summary":"Discover World State Layer declarations and runtime availability","description":"Lists authoritative State Layer declarations, their runtime availability, evidence role, methodology, rights, claim posture, and supported query links.","security":[],"parameters":[{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"claim_posture","in":"query","schema":{"type":"string","enum":["supported","provisional","not_claimed"]}}],"responses":{"200":{"description":"World State catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorldStateLayersResponse"}}}},"400":{"description":"Invalid discovery filter."}}}},"/world/v1/values":{"get":{"tags":["WorldState"],"operationId":"listStateLayerValues","summary":"Retrieve bounded, deterministic State Layer values","description":"Public read-only projection over existing records. Restricted source records remain subject to their existing authentication and redistribution boundaries.","security":[],"parameters":[{"name":"layer","in":"query","required":true,"schema":{"type":"string"}},{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"source_record","in":"query","description":"Exact source record identifier returned in lineage.source_record_ids.","schema":{"type":"string"}},{"name":"bbox","in":"query","description":"minLon,minLat,maxLon,maxLat; values without point geometry do not match.","schema":{"type":"string"}},{"name":"reference_period","in":"query","schema":{"type":"string"}},{"name":"target_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"target_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"issue_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"issue_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"source","in":"query","schema":{"type":"string"}},{"name":"quality","in":"query","schema":{"type":"string"}},{"name":"claim_posture","in":"query","schema":{"type":"string","enum":["supported","provisional","not_claimed"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"Opaque cursor bound to the exact filter set.","schema":{"type":"string"}}],"responses":{"200":{"description":"State Layer values or an honest empty state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorldStateValuesResponse"}}}},"400":{"description":"Invalid range, filter, or cursor."},"404":{"description":"Unknown State Layer identifier."},"422":{"description":"Selective filters exceeded the bounded scan; narrow the query."}}}},"/v1/global/sources":{"get":{"tags":["GlobalIntelligence"],"operationId":"listGlobalIntelligenceSources","summary":"Global source catalog and current health","description":"Returns source documentation, license/data-use links, access mode, refresh expectations, provenance policy, readiness, and sanitized health for the seven first-wave providers. Authenticated with an existing v1 API key.","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Source catalog and health","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalSourceCatalogResponse"}}}},"503":{"description":"Catalog temporarily unavailable"}}}},"/v1/global/health":{"get":{"tags":["GlobalIntelligence"],"operationId":"getGlobalIntelligenceHealth","summary":"Global source freshness and health","description":"Health describes retrieval and usable-output freshness, not provider truth or completeness. Upstream error bodies are never returned.","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Sanitized source health","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalHealthResponse"}}}},"503":{"description":"Health temporarily unavailable"}}}},"/v1/global/signals":{"get":{"tags":["GlobalIntelligence"],"operationId":"listGlobalIntelligenceSignals","summary":"Page through normalized global signals","description":"Bounded deterministic-cursor reads with source, domain, country, region, bbox, time range, and record-type filters. Null values and quality flags are preserved. UCDP is historical context, never a live danger score.","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"source","in":"query","schema":{"type":"string","enum":["gdacs","reliefweb","world-bank","who-gho","gbif","obis","ucdp"]}},{"name":"domain","in":"query","schema":{"type":"string","enum":["disaster","humanitarian","economics","health","biodiversity","marine-biodiversity","conflict-context"]}},{"name":"record_type","in":"query","schema":{"type":"string","enum":["alert","report","indicator","observation","event"]}},{"name":"country","in":"query","schema":{"type":"string","maxLength":32}},{"name":"region","in":"query","schema":{"type":"string","maxLength":120}},{"name":"bbox","in":"query","schema":{"type":"string","description":"minLon,minLat,maxLon,maxLat"}},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Normalized signal page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalSignalsResponse"}}}},"400":{"description":"Invalid filter or cursor"},"503":{"description":"Records temporarily unavailable"}}}},"/corpus/v1/situation-aware/cases":{"get":{"tags":["Corpus"],"summary":"Read materialized PM2.5 situation cases","description":"Read bounded materialized situation cases with explicit scope, evidence state, and pagination.","parameters":[{"name":"after_id","in":"query","schema":{"type":"integer","minimum":0}},{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"task_id","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"Ascending, bounded persisted case page"}}}},"/corpus/v1/situation-aware/closures":{"get":{"tags":["Corpus"],"summary":"Read append-only PM2.5 closure links","description":"Read append-only closure links that explain how scoped situation cases were closed.","parameters":[{"name":"after_id","in":"query","schema":{"type":"integer","minimum":0}},{"name":"provider_id","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"Ascending, bounded persisted closure page"}}}},"/corpus/v1/situation-aware/readiness":{"get":{"tags":["Corpus"],"summary":"Read scoped passive pilot readiness","description":"Read readiness signals for the scoped passive pilot without treating readiness as a forecast or outcome.","responses":{"200":{"description":"Manifest-scoped field coverage and qualification"}}}},"/corpus/v2/manifest":{"get":{"tags":["Corpus"],"summary":"Discover a signed, snapshot-pinned Zeno provider API","description":"Returns the immutable high-water marks and resource inventory for a consumer-owned snapshot. training_eligible is copied from explicit source declarations and is null when ingestion did not declare it; consumer admission remains a separate decision. Use the returned snapshot_id on every /corpus/v2 resource request.","operationId":"getZenoProviderManifest","security":[],"responses":{"200":{"description":"Zeno provider API manifest","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Manifest generation failed."}}}},"/corpus/v2/admission-report":{"get":{"tags":["Corpus"],"summary":"Return consumer-facing Zeno admission evidence","description":"Reports schema/reference/timing/permission status and explicit six-domain dispositions. This report never grants training eligibility and preserves PM10 quarantine plus Global Context evidence-only semantics.","operationId":"getZenoAdmissionReport","security":[],"parameters":[{"name":"snapshot_id","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Zeno admission report","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid signed snapshot."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Admission report generation failed."}}}},"/corpus/v2/{resource}":{"get":{"tags":["Corpus"],"summary":"Page one Zeno provider record resource","description":"Returns one of the nine proposed Zeno record types through a signed snapshot boundary. The API preserves nulls, abstentions, unmatched records, revisions, unknown clocks and explicit domain restrictions. Scores and performance windows are derived only from causally matched persisted forecast/outcome records; no missing outcome is zero-filled.","operationId":"getZenoProviderResource","security":[],"parameters":[{"name":"resource","in":"path","required":true,"schema":{"type":"string","enum":["models","tasks","inputs","runs","forecasts","outcomes","scores","performance-windows","events"]}},{"name":"snapshot_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"domain","in":"query","required":false,"schema":{"type":"string","enum":["air","earth","sea","agriculture","urban","global-context"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Snapshot-pinned Zeno record page","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid resource, snapshot, cursor, limit, or domain."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Zeno resource query failed; never returned as an empty success."},"503":{"description":"Derived resource exceeds the bounded adapter read budget; retry with a narrower domain."}}}},"/corpus/v1/meta":{"get":{"tags":["Corpus"],"summary":"Describe the complete public corpus","description":"The canonical Zeno/Divergent metadata endpoint. It inventories every domain and channel, declares mixed licensing explicitly, and links the matching generic entity and observation endpoints. It serves static declarations and cached snapshots without waiting for live count scans; uncached verification state is unknown and exact population counts remain unavailable until warmed in the background. Read domains[].readiness first, clamp since to first_usable_target_at, select only eligible forecast entities, and then follow opaque next_cursor values. Model channels identify their stable model family and declare uncertainty_type as interval, quantiles, or none; none never means a zero-width interval. If a channel name was qualified after an ambiguous legacy name, channel_migrations gives the explicit replacement list. This metadata is evidence-only: sparse or empty populations remain explicit and must not be interpreted as absent providers, healthy models, or zero measurements. PM10 is quarantined and Global Context is contextual evidence only.","operationId":"getCorpusInventory","security":[],"responses":{"200":{"description":"Multi-domain corpus metadata, licensing, channel definitions, history, and endpoint links.","content":{"application/json":{"schema":{"type":"object","required":["source","version","schema_version","domain_hint","entity_kind","cadence_seconds","history_start","history","entity_count","license","license_status","redistribution","channels","domains","readiness","endpoints"],"properties":{"source":{"type":"string","example":"notflat.world"},"version":{"type":"string","example":"1"},"schema_version":{"type":"string","example":"2.1.0"},"domain_hint":{"type":"string","const":"multi_domain"},"entity_kind":{"type":"string","const":"multi_domain_entity"},"cadence_seconds":{"type":"integer","minimum":1},"history_start":{"type":["string","null"],"format":"date-time"},"history":{"$ref":"#/components/schemas/CorpusHistorySummary"},"entity_count":{"type":["integer","null"],"minimum":0,"description":"Total entities when the live inventory snapshot is warm; null during cold-start warming."},"license":{"type":"string"},"license_status":{"type":"string","const":"mixed"},"redistribution":{"type":"string","const":"channel_specific"},"channels":{"type":"array","items":{"$ref":"#/components/schemas/CorpusChannel"}},"channel_migrations":{"type":"array","items":{"$ref":"#/components/schemas/CorpusChannelMigration"},"description":"Explicit compatibility mappings for renamed channel identities."},"model_families":{"type":"array","items":{"$ref":"#/components/schemas/CorpusModelFamily"},"description":"Runtime-backed, family-qualified model inventory across all domains."},"model_family_summary":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/CorpusModelFamilySummary"}},"readiness":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/CorpusTrainingReadiness"},"description":"Readiness-first discovery by domain. Consumers must not infer promotion eligibility from raw row volume."},"training_health":{"type":["object","null"],"description":"Latest AirWatch train lifecycle state from the stage health record.","properties":{"status":{"type":["string","null"],"enum":["queued","running","completed","failed","intentionally_withheld",null]},"status_at":{"type":["string","null"],"format":"date-time"},"reason":{"type":["string","null"]},"run_kind":{"type":["string","null"],"enum":["normal","recovery",null]},"scheduled_at":{"type":["string","null"],"format":"date-time"},"last_attempt_at":{"type":["string","null"],"format":"date-time"},"last_success_at":{"type":["string","null"],"format":"date-time"}}},"excluded_domains":{"type":"array","items":{"type":"object","required":["domain","reason","complete_forecast_days","required_days","attributable_prediction_rows"],"properties":{"domain":{"type":"string","example":"antifogo"},"reason":{"type":"string","enum":["insufficient_history"]},"complete_forecast_days":{"type":"integer","minimum":0},"required_days":{"type":"integer","minimum":1},"attributable_prediction_rows":{"type":"integer","minimum":0}}}},"domains":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"verification_persistence":{"type":"object","required":["sources","status","scoreability_supported"],"properties":{"sources":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["unknown","fresh","stale","failed","missing","exempt"]},"scoreability_supported":{"type":"boolean"}}}}}},"model_behaviour":{"type":"object","properties":{"population_quality":{"$ref":"#/components/schemas/ModelBehaviourPopulationQuality"}}},"endpoints":{"type":"object","additionalProperties":{"type":"string"}}}}}}},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Metadata query failed; never returned as an empty success."}}}},"/corpus/v1/entities":{"get":{"tags":["Corpus"],"summary":"List every stable corpus entity","description":"The canonical Zeno/Divergent entity endpoint. Returns a flat, domain-qualified inventory with history bounds, freshness, and observed/derived/model coverage. Use the optional domain query to narrow it.","operationId":"getAllCorpusEntities","security":[],"parameters":[{"name":"domain","in":"query","required":false,"schema":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}}],"responses":{"200":{"description":"Flat stable entity inventory.","content":{"application/json":{"schema":{"type":"object","required":["entity_count","page_count","next_cursor","terminal","entities"],"properties":{"entity_count":{"type":"integer","minimum":0},"page_count":{"type":"integer","minimum":0},"next_cursor":{"type":["string","null"]},"terminal":{"type":"boolean"},"domains":{"type":"array","items":{"type":"string"}},"entities":{"type":"array","items":{"$ref":"#/components/schemas/CorpusEntity"}}}}}}},"400":{"description":"Unknown domain."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Entity query failed; never returned as an empty success."}}}},"/corpus/v1/models":{"get":{"tags":["Corpus"],"summary":"List every declared and runtime model family","description":"Public, read-only model inventory for all corpus domains. Every declared family remains listed when unavailable, with runtime_reason explaining whether persisted output was found, stale, or could not be queried. Fetch the model's actual output rows through the linked observations endpoint and match model_id/model_version.","operationId":"getCorpusModels","security":[],"parameters":[{"name":"domain","in":"query","required":false,"schema":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}}],"responses":{"200":{"description":"Runtime-backed model family inventory with channel contracts and endpoint links.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorpusModelsResponse"}}}},"400":{"description":"Unknown domain."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Model inventory query failed; never returned as an empty success."},"503":{"description":"Model inventory capacity is temporarily unavailable; retry after the indicated delay."}}}},"/corpus/v1/{domain}/models":{"get":{"tags":["Corpus"],"summary":"List models for one corpus domain","description":"Returns the declared and runtime-backed model families for one domain. Unavailable or stale families remain explicit and are not inferred from row volume.","operationId":"getCorpusDomainModels","security":[],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}}],"responses":{"200":{"description":"Runtime-backed model family inventory for the requested domain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorpusModelsResponse"}}}},"400":{"description":"Unknown domain."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Model inventory query failed; never returned as an empty success."}}}},"/corpus/v1/model-identities":{"get":{"tags":["Corpus"],"summary":"List append-only model identities and version lineage","description":"Pages immutable provider, family, version, input, peer, and lineage identities ordered by availability. Identity continuity is evidence, not a quality score.","operationId":"getCorpusModelIdentities","security":[],"parameters":[{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"provider_id","in":"query","schema":{"type":"string"}},{"name":"family","in":"query","schema":{"type":"string"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"Model identity page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelBehaviourCollection"}}}},"400":{"description":"Invalid availability window or cursor"}}}},"/corpus/v1/forecast-runs":{"get":{"tags":["Corpus"],"summary":"List forecast runs with issue and availability clocks","description":"Pages model execution records while preserving issue, run, availability, status, and lineage clocks. A run may exist without forecast events.","operationId":"getCorpusForecastRuns","security":[],"parameters":[{"name":"model_id","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"Forecast run page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelBehaviourCollection"}}}}}}},"/corpus/v1/forecast-events":{"get":{"tags":["Corpus"],"summary":"List timestamped forecast evidence primitives and revisions","description":"Pages append-only forecast emissions with issue, target, availability, uncertainty, peer, model, and revision semantics. Pending, suppressed, failed, and unavailable emissions are not numeric zero.","operationId":"getCorpusForecastEvents","security":[],"parameters":[{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"model_id","in":"query","schema":{"type":"string"}},{"name":"model_version","in":"query","schema":{"type":"string"}},{"name":"forecast_run_id","in":"query","schema":{"type":"string"}},{"name":"emission_state","in":"query","schema":{"type":"string"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"Forecast event page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelBehaviourCollection"}}}}}}},"/corpus/v1/outcome-vintages":{"get":{"tags":["Corpus"],"summary":"List append-only outcome vintages and finalization clocks","description":"Pages observed outcome revisions with observation and availability clocks, source identity, finalization status, and revision links. Missing or late outcomes remain unavailable.","operationId":"getCorpusOutcomeVintages","security":[],"parameters":[{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"source_id","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["preliminary","final","superseded"]}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"Outcome vintage page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelBehaviourCollection"}}}}}}},"/corpus/v1/lifecycle-events":{"get":{"tags":["Corpus"],"summary":"List model lifecycle events","description":"Pages append-only model training, release, retirement, replacement, and other lifecycle transitions with their availability timestamps and related identities.","operationId":"getCorpusLifecycleEvents","security":[],"parameters":[{"name":"model_id","in":"query","schema":{"type":"string"}},{"name":"model_version","in":"query","schema":{"type":"string"}},{"name":"event_type","in":"query","schema":{"type":"string"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"Lifecycle event page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelBehaviourCollection"}}}}}}},"/corpus/v1/operational-events":{"get":{"tags":["Corpus"],"summary":"List model emission and operational state history","description":"Pages domain/entity operational state transitions such as emitting, withheld, stale, or unavailable. No event is itself evidence that operation was healthy.","operationId":"getCorpusOperationalEvents","security":[],"parameters":[{"name":"model_id","in":"query","schema":{"type":"string"}},{"name":"model_version","in":"query","schema":{"type":"string"}},{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"Operational event page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelBehaviourCollection"}}}}}}},"/corpus/v1/context-snapshots":{"get":{"tags":["Corpus"],"summary":"List cutoff-available input context snapshots","description":"Pages the input context available at declared cutoffs, preserving source references, rights, hashes, and the timing boundary needed for no-look-ahead replay.","operationId":"getCorpusContextSnapshots","security":[],"parameters":[{"name":"domain","in":"query","schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"Context snapshot page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelBehaviourCollection"}}}}}}},"/corpus/v1/snapshots":{"get":{"tags":["Corpus"],"summary":"List reproducible corpus snapshot manifests","description":"Pages complete, partial, and unavailable snapshot manifests with included resources, hashes, rights, and generation metadata. Missing sections are never silently filled.","operationId":"getCorpusSnapshots","security":[],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["complete","partial","unavailable"]}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"Snapshot manifest page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelBehaviourCollection"}}}}}}},"/corpus/v1/forecast-vintages":{"get":{"tags":["Corpus"],"summary":"Page immutable forecast/outcome timing receipts","description":"Returns legacy causal forecast/outcome verification receipts with issue, target, observation, outcome-availability, and verification clocks. run_at is unavailable and available_at aliases outcome_available_at; use forecast-events for distinct forecast emission/publication timing. Only persisted matched rows are returned, revision is currently 1, and no separate raw pre-transformation value is retained.","operationId":"getCorpusForecastVintages","security":[],"parameters":[{"name":"domain","in":"query","schema":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}},{"name":"family","in":"query","schema":{"type":"string"}},{"name":"model_version","in":"query","schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string","pattern":"^[0-9]+$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Bounded forecast/outcome receipt page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorpusForecastVintagesResponse"}}}},"400":{"description":"Invalid domain, date, cursor, or limit."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Forecast vintage query failed; never returned as an empty success."}}}},"/corpus/v1/weather-evidence":{"get":{"tags":["Corpus"],"summary":"Return source-grid-aware pressure and wind evidence census","description":"Reports surface pressure, mean-sea-level pressure, 10 m wind speed, and gust evidence with explicit units and conversions. Forecast and outcome counts distinguish source-grid evidence, issue days, and valid days; ward aliases never increase independent support. Best-match remains one seamless Open-Meteo product and unavailable revision, interval, and ensemble fields remain explicit.","operationId":"getCorpusWeatherEvidence","security":[],"responses":{"200":{"description":"Pressure and wind evidence census."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Weather evidence census failed."}}}},"/corpus/v1/evaluation":{"get":{"tags":["Corpus"],"summary":"Return provenance-preserving forecast scorecards","description":"Aggregates persisted prospective verification rows by domain, model family, model version, and unit. Point-error metrics are published when available; interval and probabilistic metrics are null when their required persisted inputs are absent. The denominators.prospective block is the aligned contract population: its forecast, outcome, and verified-intersection counts use the same prospective events and canonical matching rules as the public pairs feeds. The legacy top-level denominator fields remain for compatibility and are broader population indicators. outcome_vintage_completeness is only a presence signal, version_continuity is currently unknown, and interval plus operational-state coverage are not computed here. Null is unavailable or not applicable, never zero.","operationId":"getCorpusEvaluation","security":[],"parameters":[{"name":"domain","in":"query","schema":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}},{"name":"family","in":"query","schema":{"type":"string"}},{"name":"model_version","in":"query","schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"available_before","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Evaluation scorecards isolated by model family, version, and unit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorpusEvaluationResponse"}}}},"400":{"description":"Invalid domain or date."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Evaluation query failed; never returned as an empty success."}}}},"/corpus/v1/seismic/pairs":{"get":{"tags":["Corpus","Seismic"],"summary":"Return prospective seismic probability pairs","description":"Publishes the seismic-probability-prospective-v1 contract for M4 and M5 event probabilities at 24h, 72h, and 168h horizons. Forecasts and outcomes match only by exact canonical zone, threshold, and UTC target window. Labels mature six hours after target end. Unsupported, pooled, sparse, rejected, and unavailable opportunities remain explicit abstentions; no-event outcomes are event_count=0 and never imply a forecast probability of zero. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusSeismicPairs","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"Prospective seismic pairs plus exact-zone/threshold/horizon Brier denominators. metrics.page describes this response page; metrics.population describes the full matched population.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Seismic contract query failed; never returned as an empty success."}}}},"/corpus/v1/seismic/metrics":{"get":{"tags":["Corpus","Seismic"],"summary":"Return prospective seismic Brier denominators","description":"Alias of the prospective seismic pair response with metrics grouped by exact zone, M4/M5 threshold, and 24h/72h/168h horizon. Only emitted probabilities with mature labels enter the matched Brier denominator. Abstentions and unmatched forecasts remain visible in their own denominator fields; no aggregate score across groups is claimed. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusSeismicMetrics","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"Seismic prospective contract, pairs, group-isolated metrics, generated timestamp, and missingness semantics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Seismic metrics query failed; never returned as an empty success."}}}},"/corpus/v1/pm25/pairs":{"get":{"tags":["Corpus","Air"],"summary":"Return prospective PM2.5 forecast/outcome pairs","description":"Prospective PM2.5 forecast/outcome pairs, newest-first, with revision traversal via revision_of. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusPm25Pairs","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"PM2.5 pairs plus page/population metrics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."}}}},"/corpus/v1/pm25/metrics":{"get":{"tags":["Corpus","Air"],"summary":"Alias of PM2.5 pairs with metrics emphasis","description":"Alias of /corpus/v1/pm25/pairs. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusPm25Metrics","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"PM2.5 pairs plus page/population metrics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."}}}},"/corpus/v1/sea-sst/pairs":{"get":{"tags":["Corpus","Sea"],"summary":"Return prospective sea SST forecast/outcome pairs","description":"Prospective Sea SST forecast/outcome pairs, newest-first, with revision traversal via revision_of. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusSeaSstPairs","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"Sea SST pairs plus page/population metrics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."}}}},"/corpus/v1/sea-sst/metrics":{"get":{"tags":["Corpus","Sea"],"summary":"Alias of Sea SST pairs with metrics emphasis","description":"Alias of /corpus/v1/sea-sst/pairs. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusSeaSstMetrics","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"Sea SST pairs plus page/population metrics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."}}}},"/corpus/v1/urban-heat/pairs":{"get":{"tags":["Corpus","Urban"],"summary":"Return prospective urban heat forecast/outcome pairs","description":"Prospective urban heat forecast/outcome pairs, newest-first, with revision traversal via revision_of. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusUrbanHeatPairs","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"Urban heat pairs plus page/population metrics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."}}}},"/corpus/v1/urban-heat/metrics":{"get":{"tags":["Corpus","Urban"],"summary":"Alias of urban heat pairs with metrics emphasis","description":"Alias of /corpus/v1/urban-heat/pairs. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusUrbanHeatMetrics","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"Urban heat pairs plus page/population metrics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."}}}},"/corpus/v1/agriculture-seasonal/pairs":{"get":{"tags":["Corpus","Agriculture"],"summary":"Return prospective agriculture seasonal forecast/outcome pairs","description":"Prospective agriculture seasonal precipitation forecast/outcome pairs, newest-first, with revision traversal via revision_of. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusAgricultureSeasonalPairs","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"Agriculture seasonal pairs plus page/population metrics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."}}}},"/corpus/v1/agriculture-seasonal/metrics":{"get":{"tags":["Corpus","Agriculture"],"summary":"Alias of agriculture seasonal pairs with metrics emphasis","description":"Alias of /corpus/v1/agriculture-seasonal/pairs. Keyset-paginated, newest-first (by internal event id). Pass the response's next_cursor back as the cursor query parameter to fetch the next page; a null/absent next_cursor means the page reached the capture ceiling or the end of the matched population, whichever comes first. Revisions are traversed via each row's revision_of field, so superseded rows remain reachable from their newer revision.","operationId":"getCorpusAgricultureSeasonalMetrics","security":[],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from a previous response's next_cursor field. Omit for the first (newest) page."}],"responses":{"200":{"description":"Agriculture seasonal pairs plus page/population metrics.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid limit or cursor."},"429":{"description":"Public corpus rate limit exceeded."}}}},"/corpus/v1/observations":{"get":{"tags":["Corpus"],"summary":"Page observations without a domain adapter","description":"The canonical Zeno/Divergent observation endpoint. The domain is inferred from the stable entity ID. Rows carry stable identity, record class, temporal role, valid time, availability time, native values, and lineage. Use since and opaque cursor together for bounded chronological reads; coverage no_rows is not a zero observation.","operationId":"getGenericCorpusObservations","security":[],"parameters":[{"name":"entity","in":"query","required":true,"schema":{"type":"string"}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}}],"responses":{"200":{"description":"A bounded chronological page with explicit interval coverage.","content":{"application/json":{"schema":{"type":"object","required":["domain","entity","since","observations","next_cursor","terminal","coverage"],"properties":{"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"entity":{"type":"string"},"since":{"type":"string","format":"date-time"},"observations":{"type":"array","items":{"$ref":"#/components/schemas/CorpusObservation"}},"next_cursor":{"type":["string","null"]},"terminal":{"type":"boolean"},"coverage":{"type":"object","required":["interval_status","expected_cadence_seconds","first_returned_at","last_returned_at","record_classes","temporal_roles"],"properties":{"interval_status":{"type":"string","enum":["available","no_rows"]},"expected_cadence_seconds":{"type":"integer","minimum":1},"first_returned_at":{"type":["string","null"],"format":"date-time"},"last_returned_at":{"type":["string","null"],"format":"date-time"},"record_classes":{"type":"array","items":{"type":"string","enum":["observed","derived","model_output"]}},"temporal_roles":{"type":"array","items":{"type":"string","enum":["observation","nowcast","forecast","projection"]}}}}}}}}},"400":{"description":"Invalid entity domain, query, cursor, date, or limit."},"404":{"description":"Unknown stable entity."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Observation query failed; never returned as an empty success."}}}},"/corpus/v1/{domain}/meta":{"get":{"tags":["Corpus"],"summary":"Describe one corpus domain","description":"Returns one domain's history, readiness, model-family inventory, channel semantics, rights, cadence, verification persistence, and endpoint links. Cold verification remains unknown; exact behaviour-ledger counts warm asynchronously. Readiness and first usable target precede row retrieval.","operationId":"getCorpusMeta","security":[],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}}],"responses":{"200":{"description":"Channel definitions, stable model-family identities, explicit uncertainty semantics, rights, native resolutions, cadence, entity count, history start, and pagination policy.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["domain","schema_version","history","model_families","model_family_summary","readiness","endpoints"],"properties":{"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"schema_version":{"type":"string"},"history":{"$ref":"#/components/schemas/CorpusHistorySummary"},"model_families":{"type":"array","items":{"$ref":"#/components/schemas/CorpusModelFamily"}},"model_family_summary":{"$ref":"#/components/schemas/CorpusModelFamilySummary"},"readiness":{"$ref":"#/components/schemas/CorpusTrainingReadiness"},"verification_persistence":{"type":"object","required":["sources","status","scoreability_supported"],"properties":{"sources":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["unknown","fresh","stale","failed","missing","exempt"]},"scoreability_supported":{"type":"boolean"}}},"model_behaviour":{"type":"object","properties":{"population_quality":{"$ref":"#/components/schemas/ModelBehaviourPopulationQuality"}}},"endpoints":{"type":"object","additionalProperties":{"type":"string"}},"training_health":{"type":["object","null"],"description":"Latest AirWatch train lifecycle state; populated for the air domain.","properties":{"status":{"type":["string","null"],"enum":["queued","running","completed","failed","intentionally_withheld",null]},"status_at":{"type":["string","null"],"format":"date-time"},"reason":{"type":["string","null"]},"run_kind":{"type":["string","null"],"enum":["normal","recovery",null]},"scheduled_at":{"type":["string","null"],"format":"date-time"},"last_attempt_at":{"type":["string","null"],"format":"date-time"},"last_success_at":{"type":["string","null"],"format":"date-time"}}}}}}}},"400":{"description":"Unknown domain."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Metadata query failed; never returned as an empty success."}}}},"/corpus/v1/{domain}/entities":{"get":{"tags":["Corpus"],"summary":"List stable entities in one corpus domain","description":"Pages domain-qualified entities with stable IDs, coordinates, history bounds, freshness, observed/derived/model coverage, and any explicit source-to-forecast mapping evidence.","operationId":"getCorpusEntities","security":[],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque stable-entity continuation cursor."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}}],"responses":{"200":{"description":"Stable, domain-qualified entity identifiers with labels, coordinates, and tags.","content":{"application/json":{"schema":{"type":"object","required":["domain","entity_count","page_count","next_cursor","terminal","entities"],"properties":{"domain":{"type":"string"},"entity_count":{"type":"integer"},"page_count":{"type":"integer","minimum":0},"next_cursor":{"type":["string","null"]},"terminal":{"type":"boolean"},"entities":{"type":"array","items":{"type":"object","required":["id","label","lat","lon","tags","domain","first_observation_at","last_observation_at","first_model_valid_at","last_model_valid_at","first_forecast_target_at","last_forecast_target_at","last_available_at","freshness_status","coverage"],"properties":{"id":{"type":"string","example":"air:station:example-id"},"label":{"type":"string"},"lat":{"type":["number","null"]},"lon":{"type":["number","null"]},"tags":{"type":"array","items":{"type":"string"}},"domain":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]},"first_observation_at":{"type":["string","null"],"format":"date-time"},"last_observation_at":{"type":["string","null"],"format":"date-time"},"first_model_valid_at":{"type":["string","null"],"format":"date-time"},"last_model_valid_at":{"type":["string","null"],"format":"date-time"},"first_forecast_target_at":{"type":["string","null"],"format":"date-time"},"last_forecast_target_at":{"type":["string","null"],"format":"date-time"},"last_available_at":{"type":["string","null"],"format":"date-time"},"freshness_status":{"type":"string","enum":["active","stale","no_data"]},"forecast_entity_id":{"type":["string","null"]},"forecast_entity_relation":{"type":["string","null"],"enum":["direct","mapped",null]},"entity_mapping_version":{"type":["string","null"]},"entity_mapping_method":{"type":["string","null"]},"entity_mapping_confidence":{"type":["number","null"],"minimum":0,"maximum":1},"entity_mapping_is_fallback":{"type":["boolean","null"]},"entity_mapping_fallback":{"type":["string","null"]},"entity_mapping_evidence_id":{"type":["string","null"]},"forecast_coverage":{"$ref":"#/components/schemas/CorpusForecastCoverage"},"coverage":{"type":"object","required":["observed","derived","model_output"],"properties":{"observed":{"type":"boolean"},"derived":{"type":"boolean"},"model_output":{"type":"boolean"}}}}}}}}}}},"400":{"description":"Unknown domain."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Entity query failed; never returned as an empty success."}}}},"/corpus/v1/{domain}/entity-mappings":{"get":{"tags":["Corpus"],"summary":"Map AirWatch stations to scoreable ward entities","description":"Publishes deterministic station-to-ward attribution. Persisted and point-in-polygon mappings are authoritative. Nearest-centroid mappings are explicit fallbacks, and stations farther than 40 km from ward coverage remain unmapped. The response also reports authoritative ward and independent PM2.5 forecast-family counts.","operationId":"getCorpusEntityMappings","security":[],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","enum":["air"]}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque station-ID continuation cursor."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}}],"responses":{"200":{"description":"Versioned AirWatch station-to-ward mapping inventory and scoreability counts.","content":{"application/json":{"schema":{"type":"object","required":["domain","mapping_version","mapping_count","next_cursor","terminal","counts","scoreability_policy","forecast_families","mappings"],"properties":{"domain":{"type":"string","const":"air"},"mapping_version":{"type":"string","example":"air-station-ward-v1"},"mapping_count":{"type":"integer","minimum":0,"maximum":1000},"next_cursor":{"type":["string","null"]},"terminal":{"type":"boolean"},"counts":{"type":"object","required":["station_count","authoritative_mapping_count","fallback_mapping_count","unmapped_station_count","authoritative_ward_count","fallback_only_ward_count","scoreable_ward_count","fallback_outcome_ward_count","scoreable_forecast_family_count"],"properties":{"station_count":{"type":"integer","minimum":0},"authoritative_mapping_count":{"type":"integer","minimum":0},"fallback_mapping_count":{"type":"integer","minimum":0},"unmapped_station_count":{"type":"integer","minimum":0},"authoritative_ward_count":{"type":"integer","minimum":0},"fallback_only_ward_count":{"type":"integer","minimum":0},"scoreable_ward_count":{"type":"integer","minimum":0,"description":"Wards with a non-fallback mapped station and a valid PM2.5 observation in the last 30 days."},"fallback_outcome_ward_count":{"type":"integer","minimum":0,"description":"Wards with recent PM2.5 contributed by fallback-mapped stations; these are not included in scoreable_ward_count."},"scoreable_forecast_family_count":{"type":"integer","minimum":0}}},"scoreability_policy":{"type":"object","required":["outcome_channel","forecast_channels","outcome_window_start","authoritative_outcomes_only","fallback_outcomes_excluded_by_default","mapping_evidence_identity","forecast_outcome_join","pagination"],"properties":{"outcome_channel":{"type":"string","const":"obs.pm25"},"forecast_channels":{"type":"array","minItems":2,"items":{"type":"string","enum":["model.pm25_airwatch_calibrated","model.pm25_cams_bias_adjusted"]}},"outcome_window_start":{"type":"string","format":"date-time"},"authoritative_outcomes_only":{"type":"boolean","const":true},"fallback_outcomes_excluded_by_default":{"type":"boolean","const":true},"mapping_evidence_identity":{"type":"object","required":["field","outcome_field","algorithm","components"],"properties":{"field":{"type":"string","const":"mapping_evidence_id"},"outcome_field":{"type":"string","const":"entity_mapping_evidence_ids"},"algorithm":{"type":"string","const":"sha256-canonical-components-v1"},"components":{"type":"array","items":{"type":"string"}}}},"forecast_outcome_join":{"type":"object","required":["entity_key","target_key","alignment","tolerance_seconds","forecast_issue_key","outcome_availability_condition","episode_keys"],"properties":{"entity_key":{"type":"string","const":"entity_id"},"target_key":{"type":"string","const":"timestamp"},"alignment":{"type":"string","const":"nearest_within_window"},"tolerance_seconds":{"type":"integer","const":43200},"forecast_issue_key":{"type":"string","const":"available_at"},"outcome_availability_condition":{"type":"string"},"episode_keys":{"type":"array","items":{"type":"string"}}}},"pagination":{"type":"object","required":["cursor","ordering","source_reads","partial_aggregate_buckets","missing_outcomes"],"properties":{"cursor":{"type":"string","const":"opaque_monotonic"},"ordering":{"type":"array","items":{"type":"string"}},"source_reads":{"type":"string","const":"bounded_to_requested_page"},"partial_aggregate_buckets":{"type":"string","const":"deferred"},"missing_outcomes":{"type":"string","const":"not_reinterpreted"}}}}},"forecast_families":{"type":"array","items":{"type":"object","required":["forecast_channel","model_id","model_family","model_method"],"properties":{"forecast_channel":{"type":"string"},"model_id":{"type":"string"},"model_family":{"type":"string"},"model_method":{"type":"string"},"independence_condition":{"type":["string","null"]}}}},"mappings":{"type":"array","items":{"type":"object","required":["mapping_evidence_id","station_id","station_local_id","station_name","station_source","station_lat","station_lon","station_city","ward_id","ward_local_id","ward_name","mapping_method","mapping_version","confidence","authoritative","is_fallback","fallback_status","distance_km"],"properties":{"mapping_evidence_id":{"type":"string","pattern":"^urn:corpus:air:mapping:[0-9a-f]{32}$"},"station_id":{"type":"string"},"station_local_id":{"type":"string"},"station_name":{"type":"string"},"station_source":{"type":"string"},"station_lat":{"type":"number","minimum":-90,"maximum":90},"station_lon":{"type":"number","minimum":-180,"maximum":180},"station_city":{"type":["string","null"]},"ward_id":{"type":["string","null"]},"ward_local_id":{"type":["string","null"]},"ward_name":{"type":["string","null"]},"mapping_method":{"type":"string","enum":["persisted_ward_id","ward_boundary","nearest_ward_centroid","unmapped"]},"mapping_version":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1},"authoritative":{"type":"boolean"},"is_fallback":{"type":"boolean"},"fallback_status":{"type":"string","enum":["not_fallback","nearest_ward","outside_ward_coverage"]},"distance_km":{"type":["number","null"],"minimum":0}}}}}}}}},"404":{"description":"Mappings are not available for this domain."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Mapping query failed; never returned as an empty success."}}}},"/corpus/v1/{domain}/observations":{"get":{"tags":["Corpus"],"summary":"Page chronological observations for one entity","description":"Returns only numeric channel values. `timestamp` is event/target time; `available_at` is the documented upstream publication/model issue time, or the computation time for a platform-derived output that persists no separate issue time. `ingested_at`, when present, is the platform receipt time and is provided separately for auditability. Model-output rows also identify their model family, version, and numeric prediction horizon. `sources` names direct row producers; `lineage` separately reports verified inputs, model producers, training provenance, and explicit gaps. Open Cosmos is attributed only when a persisted scene, analysis, or non-null feature snapshot proves contribution. Use the opaque cursor until `terminal=true`.","operationId":"getCorpusObservations","security":[],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","enum":["air","earth","agriculture","sea","urban","global-context"]}},{"name":"entity","in":"query","required":true,"schema":{"type":"string"}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque monotonic continuation token."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":250}}],"responses":{"200":{"description":"A bounded page; an empty page is valid only when the entity exists and no rows match.","content":{"application/json":{"schema":{"type":"object","required":["domain","entity","since","observations","next_cursor","terminal","coverage"],"properties":{"domain":{"type":"string"},"entity":{"type":"string"},"since":{"type":"string","format":"date-time"},"observations":{"type":"array","items":{"type":"object","required":["observation_id","entity_id","record_class","temporal_role","timestamp","available_at","values","sources","source_count","revision","revision_of","lineage"],"allOf":[{"if":{"properties":{"record_class":{"const":"model_output"}}},"then":{"required":["model_id","model_version","model_family","model_method","model_inputs"]}}],"properties":{"observation_id":{"type":"string","description":"Stable entity-qualified row identifier."},"entity_id":{"type":"string","description":"Stable public entity ID this row belongs to."},"record_class":{"type":"string","enum":["observed","derived","model_output"]},"temporal_role":{"type":"string","enum":["observation","nowcast","forecast","projection"]},"timestamp":{"type":"string","format":"date-time"},"available_at":{"type":"string","format":"date-time","description":"Estimated source publication time or model issue time."},"ingested_at":{"type":["string","null"],"format":"date-time","description":"Platform receipt time, when the source record has one. Not used as available_at."},"values":{"type":"object","additionalProperties":{"type":"number"}},"sources":{"type":"array","items":{"type":"string"},"description":"Stable source/provider identifiers that directly contributed to this observation. Model input lineage is not claimed unless listed."},"source_count":{"type":"integer","minimum":0},"revision":{"type":"integer","minimum":1},"revision_of":{"type":["string","null"]},"model_id":{"type":"string","minLength":1,"description":"Stable non-generic public model identifier for model-output rows."},"model_name":{"type":"string","description":"Stable model family name for model-output rows."},"model_version":{"type":"string","minLength":1,"description":"Immutable semantic model version, distinct from a run ID."},"model_run_id":{"type":"string","description":"Dynamic execution, training, or upstream run provenance when retained."},"model_family":{"type":"string","description":"Stable methodological family identifier; cosmetic variants share a family."},"model_method":{"type":"string","description":"Human-readable forecasting method."},"model_inputs":{"type":"array","items":{"type":"string"},"description":"Effective input families used by this forecast."},"independence_reference_model_id":{"type":"string"},"independence_reference_model_run_id":{"type":"string"},"independence_basis":{"type":"string"},"issued_entity_id":{"type":"string","description":"Stable public entity ID the model forecast was issued for."},"issued_entity_kind":{"type":"string"},"entity_attribution":{"type":"string","enum":["direct","mapped"]},"entity_mapping_version":{"type":"string"},"entity_mapping_method":{"type":"string"},"entity_mapping_confidence":{"type":"number","minimum":0,"maximum":1},"entity_mapping_fallback":{"type":"boolean","description":"True only for a non-authoritative fallback attribution. Default corpus scoring excludes these outcomes."},"prediction_horizon_seconds":{"type":"integer","minimum":0,"description":"Seconds from issue time to target time; zero for current-state model estimates."},"lineage":{"type":"object","required":["status","producer","inputs","training_sources","limitations"],"description":"Verified evidence chain for this row. Possible/configured providers are never presented as actual contributors.","properties":{"status":{"type":"string","enum":["complete","partial","unavailable"]},"producer":{"anyOf":[{"type":"null"},{"$ref":"#/components/schemas/CorpusLineageEntry"}]},"inputs":{"type":"array","items":{"$ref":"#/components/schemas/CorpusLineageEntry"}},"training_sources":{"type":"array","items":{"$ref":"#/components/schemas/CorpusLineageEntry"}},"limitations":{"type":"array","items":{"type":"string"}}}}}}},"next_cursor":{"type":["string","null"]},"terminal":{"type":"boolean"},"coverage":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid query, cursor, domain, date, or limit."},"404":{"description":"Unknown stable entity."},"429":{"description":"Public corpus rate limit exceeded."},"500":{"description":"Observation query failed; never returned as an empty success."}}}},"/v1/assets/exposure":{"post":{"tags":["AssetExposure"],"summary":"Batch asset exposure query","description":"Accepts a list of named assets (Point, Polygon, or LineString geometries) and returns, for each asset, an `exposure` object per requested Earth Intelligence domain. The platform adds evidence citations, exposure flags, severity levels, freshness timestamps, and human-readable summaries.\n\n**Nothing is stored.** Asset IDs and geometries are treated as ephemeral request-scoped data and are never written to any platform table.\n\n**Auth:** required — pass your API key in `Authorization: Bearer <key>` or `X-API-Key: <key>`.\n\n**Rate limit:** 20 requests/minute per API key.\n\n**Limits:** 50 assets per request; 5 domains per request; `radius_km` max 300 km.\n\n**Exposure thresholds (static):**\n- `air`: exposed = any Delhi/Mumbai ward monitoring point within radius (live PM2.5 requires `GET /v1/wards/:wardId/current`; severity always null at entity level)\n- `earth`: exposed = any seismic event M≥4.0; severity: high ≥ M6.0 | moderate ≥ M4.0 | low < M4.0\n- `sea`: exposed = any ocean condition observation within radius; severity high if SST anomaly > 2°C, otherwise moderate\n- `urban`: exposed = any satellite scene overlaps search radius; severity moderate\n- `agriculture`: exposed = any crop district centroid within radius; severity null (live stress signals require `GET /agro/districts/:districtId`)","operationId":"postAssetExposure","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["assets","domains"],"properties":{"assets":{"type":"array","minItems":1,"maxItems":50,"description":"List of named assets to check. Maximum 50 per request.","items":{"type":"object","required":["asset_id","geometry"],"properties":{"asset_id":{"type":"string","minLength":1,"maxLength":200,"description":"Caller-stable asset identifier. Always echoed back unchanged so the agent can match results to its own records.","example":"facility-001"},"label":{"type":"string","maxLength":500,"nullable":true,"description":"Human-readable label for display purposes. Optional.","example":"Refinery Alpha"},"geometry":{"description":"GeoJSON geometry. Supported types: Point, Polygon, LineString.","oneOf":[{"title":"Point","type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2,"description":"[lng, lat] in WGS-84.","example":[77.209,28.614]}}},{"title":"Polygon","type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Polygon"]},"coordinates":{"type":"array","description":"GeoJSON Polygon ring array (exterior ring first)."}}},{"title":"LineString","type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["LineString"]},"coordinates":{"type":"array","description":"GeoJSON LineString positions array ([lng, lat] pairs)."}}}]}}}},"domains":{"type":"array","items":{"type":"string","enum":["air","earth","sea","urban","agriculture"]},"minItems":1,"maxItems":5,"description":"Domains to check for each asset. Maximum 5 per request.","example":["air","earth"]},"observed_after":{"type":"string","format":"date-time","nullable":true,"description":"ISO-8601 lower bound for temporal evidence (earth, sea, urban). Ignored for entity-based domains (air, agriculture).","example":"2026-07-01T00:00:00Z"},"radius_km":{"type":"number","minimum":0.001,"maximum":300,"default":50,"description":"Search radius from the asset geometry centroid in kilometres. Default 50 km."},"items_per_domain":{"type":"integer","minimum":1,"maximum":50,"default":10,"description":"Maximum evidence items to consider per domain per asset. Higher values improve completeness but increase latency. Default 10."}}},"example":{"assets":[{"asset_id":"facility-001","label":"Refinery Alpha","geometry":{"type":"Point","coordinates":[77.209,28.614]}},{"asset_id":"port-kochi","label":"Kochi Port","geometry":{"type":"Point","coordinates":[76.267,9.966]}}],"domains":["air","earth"],"observed_after":"2026-07-01T00:00:00Z","radius_km":25}}}},"responses":{"200":{"description":"Per-asset exposure results. All assets are returned even when exposure is false.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute for this key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["assets","meta"],"properties":{"assets":{"type":"array","items":{"type":"object","required":["asset_id","geometry","exposure"],"properties":{"asset_id":{"type":"string","description":"Caller-supplied ID, echoed back unchanged."},"label":{"type":"string","nullable":true},"geometry":{"description":"Caller-supplied geometry, echoed back unchanged."},"exposure":{"type":"object","description":"One key per requested domain.","additionalProperties":{"type":"object","required":["exposed","evidence_ids","max_severity","summary","freshness"],"properties":{"exposed":{"type":"boolean","description":"true = at least one qualifying evidence item found within radius; false = no evidence or all evidence below threshold."},"evidence_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Stable UUID-v5 evidence IDs from EvidenceEnvelope. Use POST /v1/evidence/query to retrieve the full envelopes."},"max_severity":{"type":"string","enum":["high","moderate","low"],"nullable":true,"description":"Highest severity level found. null when severity cannot be derived at entity level (air wards, agriculture districts)."},"summary":{"type":"string","description":"Human-readable exposure summary for the domain."},"freshness":{"nullable":true,"type":"object","properties":{"observed_at":{"type":"string","format":"date-time","description":"ISO-8601 timestamp of the newest contributing evidence item."},"staleness_seconds":{"type":"integer","description":"Age of the newest evidence item in seconds at response generation time. Use to judge whether evidence is current enough for a decision."}}}}}}}}},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"domains_queried":{"type":"array","items":{"type":"string"}},"radius_km":{"type":"number"},"observed_after":{"type":"string","format":"date-time","nullable":true},"asset_count":{"type":"integer"},"items_per_domain":{"type":"integer"}}}}}}}},"400":{"description":"Validation error — invalid body, duplicate asset_ids, or limits exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_request","duplicate_asset_ids","too_many_assets","too_many_domains"]},"message":{"type":"string"},"details":{"type":"array","nullable":true,"items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"max_assets":{"type":"integer","nullable":true,"example":50},"max_domains":{"type":"integer","nullable":true,"example":5}}}}}},"401":{"description":"Missing, invalid, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Per-minute rate limit exceeded or monthly quota exhausted.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limit_exceeded","quota_exceeded"]},"message":{"type":"string"},"retry_after_seconds":{"type":"integer","nullable":true},"resetAt":{"type":"string","format":"date-time","nullable":true}}}}}}}}},"/v1/satellite/coverage":{"get":{"tags":["SatelliteArchive"],"summary":"Check satellite coverage for a bounding box","description":"Returns whether the platform's Open Cosmos archive contains any scenes intersecting the requested bounding box, filtered optionally by domain and acquisition time.\n\n**No live OC API calls are made** — this endpoint queries only the platform's own mirrored `satellite_scenes` table.\n\n**Auth:** required. **Rate limit:** 60 req/min per key.","operationId":"getSatelliteCoverage","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"bbox","in":"query","required":true,"schema":{"type":"string","example":"76.8,28.3,77.6,29.0"},"description":"minLng,minLat,maxLng,maxLat (WGS-84 decimal degrees)."},{"name":"domain","in":"query","required":false,"schema":{"type":"string","enum":["air","earth","sea","urban","agriculture"]},"description":"Restrict to scenes that contribute to this Earth Intelligence domain. Omit to return all scenes regardless of domain."},{"name":"acquired_after","in":"query","required":false,"schema":{"type":"string","format":"date-time","example":"2026-01-01T00:00:00Z"},"description":"ISO-8601 lower bound for scene acquisition time (capturedAt)."}],"responses":{"200":{"description":"Coverage result for the requested bbox.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["has_coverage","most_recent_scene","scenes_in_range","provider","data_latency_hours","meta"],"properties":{"has_coverage":{"type":"boolean","description":"true if at least one scene intersects the bbox under the given filters."},"most_recent_scene":{"nullable":true,"type":"object","description":"Metadata for the most recently acquired matching scene. null when has_coverage is false.","properties":{"scene_id":{"type":"string"},"acquired_at":{"type":"string","format":"date-time","nullable":true},"provider":{"type":"string","enum":["open-cosmos","sentinel-2","landsat","other"]},"collection_id":{"type":"string"},"cloud_cover_pct":{"type":"integer","nullable":true},"resolution_m":{"type":"number","nullable":true,"description":"Nominal GSD in metres."},"processing_level":{"type":"string","example":"L1C"},"footprint":{"nullable":true,"description":"GeoJSON Polygon bounding box of the scene."},"domain":{"type":"string"},"parameters_measured":{"type":"array","items":{"type":"string"}}}},"scenes_in_range":{"type":"integer","description":"Total count of scenes intersecting the bbox (not just the most recent)."},"provider":{"type":"string","enum":["open-cosmos","sentinel-2","landsat","other"],"nullable":true,"description":"Provider of the most recent scene. null when has_coverage is false."},"data_latency_hours":{"type":"number","nullable":true,"description":"Hours between scene acquisition and availability in the platform archive. null when capturedAt is missing from the row."},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"bbox_queried":{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4},"domain_filter":{"type":"string","nullable":true},"acquired_after":{"type":"string","format":"date-time","nullable":true}}}}}}}},"400":{"description":"Invalid bbox or domain parameter.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"retry_after_seconds":{"type":"integer"},"resetAt":{"type":"string","format":"date-time"}}}}}}}}},"/v1/satellite/scenes":{"get":{"tags":["SatelliteArchive"],"summary":"List satellite scenes for a bounding box","description":"Returns a cursor-paginated list of scenes from the platform's Open Cosmos archive that intersect the requested bounding box. Each scene item includes a stable `evidence_id` (UUID-v5) that can be passed to `POST /v1/evidence/query` for the full evidence envelope, plus spectral parameters measured, domain tags, access limitations, and a GeoJSON footprint.\n\n**No live OC API calls** — DB-only.\n\n**Auth:** required. **Rate limit:** 60 req/min. **Max page size:** 100.","operationId":"getSatelliteScenes","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"bbox","in":"query","required":true,"schema":{"type":"string","example":"76.8,28.3,77.6,29.0"},"description":"minLng,minLat,maxLng,maxLat."},{"name":"domain","in":"query","required":false,"schema":{"type":"string","enum":["air","earth","sea","urban","agriculture"]}},{"name":"acquired_after","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque pagination cursor from `pagination.next_cursor` in a previous response."}],"responses":{"200":{"description":"Paginated scene list.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["scenes","pagination","meta"],"properties":{"scenes":{"type":"array","items":{"type":"object","required":["evidence_id","scene_id","provider","collection_id","acquired_at","processed_at","domain","parameters_measured","limitations"],"properties":{"evidence_id":{"type":"string","format":"uuid","description":"Stable UUID-v5 evidence ID — same ID every time for the same scene/day bucket."},"scene_id":{"type":"string"},"provider":{"type":"string","enum":["open-cosmos","sentinel-2","landsat","other"]},"collection_id":{"type":"string","example":"hammer-l1c-cogs"},"acquired_at":{"type":"string","format":"date-time","nullable":true},"processed_at":{"type":"string","format":"date-time","description":"Platform ingest timestamp."},"footprint":{"nullable":true,"description":"GeoJSON Polygon scene bounding box."},"cloud_cover_pct":{"type":"integer","nullable":true},"resolution_m":{"type":"number","nullable":true},"parameters_measured":{"type":"array","items":{"type":"string"},"example":["HOT","NDVI","NDRE","haze_index"]},"domain":{"type":"string","example":"air"},"limitations":{"type":"array","items":{"type":"string"},"description":"Known access or quality limitations for this collection."}}}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"total_in_range":{"type":"integer"},"has_next_page":{"type":"boolean"},"next_cursor":{"type":"string","nullable":true}}},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"bbox_queried":{"type":"array","items":{"type":"number"}},"domain_filter":{"type":"string","nullable":true},"acquired_after":{"type":"string","format":"date-time","nullable":true},"attribution":{"type":"string"},"attribution_url":{"type":"string"},"note":{"type":"string"}}}}}}}},"400":{"description":"Invalid parameters.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/v1/satellite/readiness":{"get":{"tags":["SatelliteArchive"],"summary":"Satellite tasking-readiness and archive metadata for a bounding box","description":"Returns per-provider readiness metadata for a bounding box: archive coverage, the most recent acquisition date, estimated revisit cadence, nominal resolution, and tasking availability (always `false` — approval-gated tasking is a separate, later endpoint).\n\nUse this endpoint to answer **'does Open Cosmos have usable coverage here, and when could they acquire again?'** without making any tasking request.\n\n- `tasking_available: false` for all providers currently — the field exists so agents do not need to check for a missing key.\n- `estimated_revisit_days` is derived from static fleet cadence data (not a live OC query); actual revisit depends on orbit geometry, cloud cover, and tasking priority.\n\n**Auth:** required. **Rate limit:** 60 req/min.","operationId":"getSatelliteReadiness","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"bbox","in":"query","required":true,"schema":{"type":"string","example":"76.8,28.3,77.6,29.0"},"description":"minLng,minLat,maxLng,maxLat."}],"responses":{"200":{"description":"Per-provider readiness metadata.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["providers","bbox_queried","generated_at"],"properties":{"providers":{"type":"object","description":"Keys are provider slugs (e.g. `open-cosmos`). Will always contain `open-cosmos` even if archive_coverage is false — agents do not need to check for a missing key.","additionalProperties":{"type":"object","required":["archive_coverage","latest_acquisition","estimated_revisit_days","nominal_resolution_m","tasking_available","tasking_note","open_cosmos_contribution"],"properties":{"archive_coverage":{"type":"boolean","description":"true if at least one archived scene intersects this bbox."},"latest_acquisition":{"type":"string","format":"date-time","nullable":true,"description":"ISO-8601 timestamp of the most recent scene acquired for this bbox."},"estimated_revisit_days":{"type":"number","nullable":true,"description":"Estimated days between satellite passes (static fleet cadence; not a live OC API call). Actual revisit varies with orbit geometry, cloud cover, and tasking priority."},"nominal_resolution_m":{"type":"number","description":"Best available GSD in metres across collections found in the archive for this bbox."},"tasking_available":{"type":"boolean","description":"Always false — approval-gated tasking is a separate endpoint not yet exposed."},"tasking_note":{"type":"string","example":"Tasking requests require approval; contact your Open Cosmos account manager."},"open_cosmos_contribution":{"type":"string","description":"Human-readable description of what Open Cosmos data covers this bbox and when it was last acquired."}}}},"bbox_queried":{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4,"description":"[minLng, minLat, maxLng, maxLat] as parsed from the bbox parameter."},"generated_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid bbox.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/v1/compound-risk/active":{"get":{"tags":["CompoundRiskV1"],"summary":"Active compound risk events with evidence IDs and methodology (v1)","description":"Returns currently active compound risk events. Each event includes:\n\n- `evidence_ids` — stable `urn:evidence:<domain>:<entity>:<date>` IDs of the domain signals that triggered this event\n- `combination_methodology.slug` — machine-readable join strategy (e.g. `threshold_join_fires_24h_wind_6h_pm25_6h`)\n- `time_alignment` — look-back window hours, oldest and newest contributing observation timestamps\n- `spatial_alignment` — join geometry method (`centroid_distance`, `bbox_intersect`, or `ward_boundary`) and max distance\n- `confidence` — `high/moderate/low` level, human basis string, and `missing_inputs[]` for signals that were unavailable\n- `limitations[]` — known caveats about data quality or inference gaps for this event\n\nEvents persisted before the evidence-linked schema was deployed return `combination_methodology.slug: 'legacy_unstructured'` and `confidence.level: 'low'` as a safe fallback.\n\n**Filters:** `?domain=` (primary or secondary domain), `?bbox=minLng,minLat,maxLng,maxLat` (in-memory spatial filter on `affected_regions` coordinates), `?updated_since=<ISO>` (incremental polling — events with `ingestedAt >= updated_since`).\n\n**Caching:** Responses are cached for 5 minutes keyed by domain. `ETag` and `Last-Modified` headers are set; clients should use `If-None-Match` for efficient polling.\n\n**Auth:** required. **Rate limit:** 60 req/min.","operationId":"listCompoundRiskActiveV1","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"domain","in":"query","required":false,"schema":{"type":"string","example":"air"},"description":"Filter by primary or secondary domain (`air`, `earth`, `sea`, `agro`, `urban`, `flood`)."},{"name":"bbox","in":"query","required":false,"schema":{"type":"string","example":"60.0,5.0,100.0,40.0"},"description":"minLng,minLat,maxLng,maxLat in WGS-84. In-memory spatial filter on `affected_regions` coordinates. Events with no extractable coordinates are included (no false negatives)."},{"name":"updated_since","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"ISO-8601 UTC. Only return events with `ingestedAt >= updated_since`. Use for incremental polling."}],"responses":{"200":{"description":"Active compound risk events with evidence metadata.","headers":{"ETag":{"schema":{"type":"string"},"description":"Stable hash of the events array. Pass as `If-None-Match` on repeat calls."},"Last-Modified":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["schema_version","events","count","generated_at","filters"],"properties":{"schema_version":{"type":"string","example":"1.0.0"},"events":{"type":"array","items":{"$ref":"#/components/schemas/CompoundRiskEventV1"}},"count":{"type":"integer"},"generated_at":{"type":"string","format":"date-time"},"filters":{"type":"object","properties":{"domain":{"type":"string","nullable":true},"bbox":{"type":"array","items":{"type":"number"},"nullable":true},"updated_since":{"type":"string","format":"date-time","nullable":true}}}}},"examples":{"active":{"summary":"Two active events with evidence metadata","externalValue":"/docs/agent-sample-responses/compound-risk-v1-active.json"},"empty":{"summary":"No events match the applied filters","externalValue":"/docs/agent-sample-responses/compound-risk-v1-empty.json"}}}}},"400":{"description":"Invalid bbox or updated_since.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/v1/compound-risk/history":{"get":{"tags":["CompoundRiskV1"],"summary":"Historical resolved compound risk events with evidence IDs (v1)","description":"Returns resolved (inactive) compound risk events within a lookback window, with the same evidence-linked fields as the active endpoint.\n\nAlso includes a `frequency_chart` array grouped by month × risk type for trend analysis.\n\n**Filters:** `?days=` (default 90, max 365), `?domain=`, `?bbox=`.\n\n**Caching:** 5-minute cache. `ETag` and `Last-Modified` headers set.\n\n**Auth:** required. **Rate limit:** 60 req/min.","operationId":"listCompoundRiskHistoryV1","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":365,"default":90},"description":"Lookback window in days. Default 90, max 365."},{"name":"domain","in":"query","required":false,"schema":{"type":"string","example":"agro"},"description":"Filter by primary or secondary domain."},{"name":"bbox","in":"query","required":false,"schema":{"type":"string","example":"60.0,5.0,100.0,40.0"},"description":"minLng,minLat,maxLng,maxLat in WGS-84."}],"responses":{"200":{"description":"Resolved compound risk events with evidence metadata and frequency chart.","headers":{"ETag":{"schema":{"type":"string"}},"Last-Modified":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["schema_version","events","frequency_chart","count","query_days","generated_at"],"properties":{"schema_version":{"type":"string","example":"1.0.0"},"events":{"type":"array","items":{"$ref":"#/components/schemas/CompoundRiskEventV1"}},"frequency_chart":{"type":"array","description":"Monthly event frequency broken down by risk type. Each entry has a `month` (YYYY-MM) key and one key per risk type with a count.","items":{"type":"object","required":["month"],"properties":{"month":{"type":"string","example":"2026-07"}},"additionalProperties":{"type":"integer"}}},"count":{"type":"integer"},"query_days":{"type":"integer"},"generated_at":{"type":"string","format":"date-time"},"filters":{"type":"object","properties":{"domain":{"type":"string","nullable":true},"bbox":{"type":"array","items":{"type":"number"},"nullable":true}}}}}}}},"400":{"description":"Invalid parameter.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/v1/satellite/tasking-requests":{"post":{"tags":["SatelliteTasking"],"summary":"Submit a satellite tasking request for human review","description":"Submits an area-of-interest (GeoJSON Polygon) and observation window for human review.\n\n**Critical:** No Open Cosmos acquisition is ever scheduled by this call. The request is recorded with `status: 'pending_review'` and routed to a human operator. Submitting a request does **not** guarantee an acquisition will be made.\n\n**Approval lifecycle:**\n`pending_review` → `approved` (operator schedules OC acquisition) or `rejected` (operator denies)\n`approved` → `fulfilled` (acquisition completed and scene ingested into /v1/satellite/scenes)\n\nPoll `GET /v1/satellite/tasking-requests/{request_id}` to check status. Allow at least 48 hours for the initial review.\n\n**Auth:** required. **Role:** `satellite_tasking` must be enabled on your key. Free-tier keys without this role receive 403. Contact the platform team to apply for access.\n\n**Geometry limits:** Polygon only (no MultiPolygon); exterior ring only; max area 25,000 km².\n\n**Observation window:** must be ≥ 1 hour, ≤ 90 days, and must start in the future.","operationId":"postSatelliteTaskingRequest","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["geometry","observation_window","purpose","domain"],"properties":{"geometry":{"type":"object","required":["type","coordinates"],"description":"GeoJSON Polygon. Exterior ring only. Maximum area 25,000 km².","properties":{"type":{"type":"string","enum":["Polygon"]},"coordinates":{"type":"array","description":"GeoJSON Polygon ring array (exterior ring first, [lon, lat] pairs)."}},"example":{"type":"Polygon","coordinates":[[[77,28.3],[77.8,28.3],[77.8,29],[77,29],[77,28.3]]]}},"observation_window":{"type":"object","required":["start","end"],"description":"ISO-8601 UTC time window within which an acquisition should occur. Must be ≥ 1 hour and ≤ 90 days, starting in the future.","properties":{"start":{"type":"string","format":"date-time","example":"2026-08-01T00:00:00Z"},"end":{"type":"string","format":"date-time","example":"2026-08-15T23:59:59Z"}}},"purpose":{"type":"string","minLength":10,"maxLength":500,"description":"Free-text justification for the tasking request. Required for operator review.","example":"Air quality corridor assessment to validate CAMS PM2.5 reanalysis for Delhi NCR."},"domain":{"type":"string","enum":["air","urban","agriculture","sea"],"description":"Earth Intelligence domain this tasking request supports."},"requested_by_asset_ids":{"type":"array","items":{"type":"string","maxLength":200},"maxItems":20,"nullable":true,"description":"Optional caller-supplied asset IDs that motivated this request. Echoed back in status responses for correlation."}}}}}},"responses":{"202":{"description":"Request recorded with `status: 'pending_review'`. The response includes a `request_id` for polling. No acquisition is scheduled until a human operator approves.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SatelliteTaskingRequestStatus"},"examples":{"pending":{"summary":"Request accepted and pending review","externalValue":"/docs/agent-sample-responses/satellite-tasking-request-pending.json"}}}}},"400":{"description":"Validation error — invalid geometry, area too large, or observation window out of range.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"area_too_large"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object"},"nullable":true}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key does not have the `satellite_tasking` role.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"satellite_tasking_not_enabled"},"message":{"type":"string"},"upgrade_url":{"type":"string","format":"uri"}}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/v1/satellite/tasking-requests/{request_id}":{"get":{"tags":["SatelliteTasking"],"summary":"Poll the status of a satellite tasking request","description":"Returns the current status and any reviewer note for a previously submitted tasking request.\n\nOnly the API key that submitted the request may read it (ownership check).\n\n**Status values:**\n- `pending_review` — awaiting human review (allow ≤ 48 h)\n- `approved` — operator has approved; acquisition is being scheduled with Open Cosmos\n- `rejected` — operator declined; `reviewer_note` explains why\n- `fulfilled` — acquisition complete; the scene will appear in `GET /v1/satellite/scenes`\n\n**Auth:** required. **Role:** `satellite_tasking` must be enabled on your key.","operationId":"getSatelliteTaskingRequest","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The `request_id` returned from `POST /v1/satellite/tasking-requests`."}],"responses":{"200":{"description":"Tasking request status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SatelliteTaskingRequestStatus"},"examples":{"approved":{"summary":"Request approved by operator","externalValue":"/docs/agent-sample-responses/satellite-tasking-request-approved.json"},"rejected":{"summary":"Request rejected by operator","externalValue":"/docs/agent-sample-responses/satellite-tasking-request-rejected.json"}}}}},"400":{"description":"Invalid request ID format.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key does not have the `satellite_tasking` role, or does not own this request.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"No tasking request found with this ID.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/v1/me":{"get":{"tags":["Auth"],"summary":"Verify API key","x-min-tier":"free","description":"Returns the tier and key ID for the authenticated key. Use this to confirm your key is valid and to inspect which plan you are on.","operationId":"getMe","responses":{"200":{"description":"Key is valid.","content":{"application/json":{"schema":{"type":"object","properties":{"tier":{"$ref":"#/components/schemas/ApiTier"},"keyId":{"type":"integer","example":12},"usageThisMonth":{"type":"integer","description":"Number of API calls made in the current billing month.","example":153},"monthlyQuota":{"type":"integer","description":"Total calls allowed per month for this key.","example":1000},"remainingThisMonth":{"type":"integer","description":"Calls remaining before quota is exhausted.","example":847},"resetAt":{"type":"string","format":"date-time","description":"ISO-8601 timestamp when the monthly quota resets (UTC).","example":"2024-11-01T00:00:00.000Z"},"message":{"type":"string","example":"API key is valid."}}},"example":{"tier":"free","keyId":12,"usageThisMonth":153,"monthlyQuota":1000,"remainingThisMonth":847,"resetAt":"2024-11-01T00:00:00.000Z","message":"API key is valid."}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Monthly quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotaError"}}}}}}},"/v1/capabilities":{"get":{"tags":["Capabilities"],"summary":"Platform capabilities manifest","security":[],"description":"Returns the full platform capabilities manifest: all five Earth Intelligence domains (air, earth, sea, urban, agriculture) with geographic coverage, available metric slugs, refresh frequency, spatial query types, forecast availability, and known limitations. No authentication required. schema_version and generated_at fields allow consumers to detect stale cached copies.","operationId":"getCapabilities","responses":{"200":{"description":"Platform capabilities manifest.","content":{"application/json":{"schema":{"type":"object","required":["schema_version","platform","generated_at","domains"],"properties":{"schema_version":{"type":"string","example":"1.0.0"},"platform":{"type":"string","example":"earth-intelligence"},"generated_at":{"type":"string","format":"date-time"},"capabilities_url":{"type":"string","format":"uri"},"openapi_url":{"type":"string","format":"uri"},"domains":{"type":"array","items":{"type":"object","properties":{"domain_id":{"type":"string","enum":["air","earth","sea","urban","agriculture"]},"display_name":{"type":"string"},"description":{"type":"string"},"status_url":{"type":"string","format":"uri"},"observations":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"unit":{"type":"string"},"description":{"type":"string"}}}},"geographic_coverage":{"type":"object","properties":{"type":{"type":"string"},"bbox":{"type":"array","items":{"type":"number"}},"description":{"type":"string"}}},"temporal_coverage":{"type":"object","properties":{"start":{"type":"string","format":"date"},"ongoing":{"type":"boolean"},"note":{"type":"string"}}},"refresh_frequency_seconds":{"type":"integer"},"spatial_query_types":{"type":"array","items":{"type":"string"}},"forecast_available":{"type":"boolean"},"provenance_supported":{"type":"boolean"},"known_limitations":{"type":"array","items":{"type":"string"}}}}}}}}}}}}},"/v1/evidence/query":{"post":{"tags":["EvidenceQuery"],"summary":"Cross-domain spatial/temporal evidence query","security":[],"description":"Returns EvidenceEnvelope items from one or more Earth Intelligence domains (air, earth, sea, urban, agriculture) that intersect a supplied geometry and optional temporal window. No free-form SQL or natural-language parsing. Results are paginated with an opaque cursor; pass `next_cursor` from the previous response to retrieve the next page.\n\n**Rate limits:** 10 req/min unauthenticated; 60 req/min with an API key.\n\n**Max geometry area:** 5,000,000 km². Requests exceeding this return 422.","operationId":"postEvidenceQuery","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["geometry","domains"],"properties":{"geometry":{"description":"Query geometry. One of BBox, Circle, or GeoJSON Polygon.","oneOf":[{"title":"BBox","type":"object","required":["type","bbox"],"properties":{"type":{"type":"string","enum":["BBox"]},"bbox":{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4,"description":"[minLng, minLat, maxLng, maxLat] in WGS-84.","example":[68,8,97.5,37.5]}}},{"title":"Circle","type":"object","required":["type","center","radius_km"],"properties":{"type":{"type":"string","enum":["Circle"]},"center":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2,"description":"[lng, lat] in WGS-84.","example":[77.209,28.614]},"radius_km":{"type":"number","minimum":0.001,"maximum":5000,"description":"Radius in kilometres.","example":300}}},{"title":"Polygon","type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Polygon"]},"coordinates":{"type":"array","description":"GeoJSON Polygon coordinates (exterior ring first)."}}}]},"domains":{"type":"array","items":{"type":"string","enum":["air","earth","sea","urban","agriculture"]},"minItems":1,"maxItems":5,"description":"Explicit allowlist of domains to query. Never auto-selected.","example":["earth","sea"]},"observed_after":{"type":"string","format":"date-time","nullable":true,"description":"ISO-8601 inclusive lower bound on observed_at. Ignored for spatial-entity domains (air, agriculture) that have no event timestamps.","example":"2026-01-01T00:00:00Z"},"observed_before":{"type":"string","format":"date-time","nullable":true,"description":"ISO-8601 exclusive upper bound on observed_at.","example":"2026-07-01T00:00:00Z"},"updated_since":{"type":"string","format":"date-time","nullable":true,"description":"ISO-8601 lower bound on updated_at. Use for incremental polling to fetch only new or revised items.","example":"2026-07-28T00:00:00Z"},"limit":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Maximum items to return per page."},"cursor":{"type":"string","nullable":true,"description":"Opaque pagination cursor from `next_cursor` in a previous response. Changing any query parameter other than `limit` while supplying a cursor returns 400."}}},"example":{"geometry":{"type":"BBox","bbox":[68,8,97.5,37.5]},"domains":["earth","sea"],"observed_after":"2026-01-01T00:00:00Z","observed_before":"2026-07-01T00:00:00Z","limit":50}}}},"responses":{"200":{"description":"Paginated list of EvidenceEnvelope items (empty list is a valid 200 response).","headers":{"ETag":{"schema":{"type":"string"},"description":"Cache key for this query + minute bucket."},"Last-Modified":{"schema":{"type":"string"},"description":"RFC-7231 timestamp of response generation."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per minute for your access level."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the rate limit window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["items","total_matched","next_cursor","meta"],"properties":{"items":{"type":"array","description":"EvidenceEnvelope items matching the query.","items":{"type":"object","description":"EvidenceEnvelope with an additional `query_geometry_matched` boolean. `true` = the entity geometry truly intersects the query geometry; `false` = the entity centroid was within the query bounding box but not the precise geometry.","properties":{"evidence_id":{"type":"string","format":"uuid","description":"UUID-v5 stable identifier."},"domain":{"type":"string","enum":["air","earth","sea","urban","agriculture"]},"evidence_type":{"type":"string","enum":["observation","derived","forecast","fixture"]},"geometry":{"nullable":true,"description":"GeoJSON Point or Polygon, or null."},"observed_at":{"type":"string","format":"date-time","nullable":true},"acquired_at":{"type":"string","format":"date-time","nullable":true},"processed_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"valid_until":{"type":"string","format":"date-time","nullable":true},"metrics":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"number"},"unit":{"type":"string"},"uncertainty_pct":{"type":"number","nullable":true}}}},"confidence":{"type":"object","properties":{"level":{"type":"string","enum":["high","moderate","low","unknown"]},"basis":{"type":"string"}}},"provenance":{"nullable":true},"warnings":{"type":"array","items":{"type":"string"}},"limitations":{"type":"array","items":{"type":"string"}},"detail":{"type":"object","description":"Domain-specific data."},"query_geometry_matched":{"type":"boolean","description":"true = entity geometry precisely intersects the query geometry; false = only the coarse bounding-box matched."}}}},"total_matched":{"type":"integer","description":"Total items matching the query (across all pages for this page's fetch batch).","example":47},"next_cursor":{"type":"string","nullable":true,"description":"Opaque cursor for the next page. null when the result set is exhausted."},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"domains_queried":{"type":"array","items":{"type":"string"}},"geometry_type":{"type":"string"},"area_km2_approx":{"type":"integer"},"observed_after":{"type":"string","format":"date-time","nullable":true},"observed_before":{"type":"string","format":"date-time","nullable":true},"updated_since":{"type":"string","format":"date-time","nullable":true},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}}}},"400":{"description":"Invalid request body, unsupported geometry type, or invalid cursor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Geometry area exceeds the 5,000,000 km² maximum.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"geometry_too_large"},"message":{"type":"string"},"area_km2_approx":{"type":"integer"},"max_area_km2":{"type":"integer","example":5000000}}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"rate_limit_exceeded"},"message":{"type":"string"},"retry_after_seconds":{"type":"integer"}}}}}}}}},"/v1/wards":{"get":{"tags":["Wards"],"summary":"List wards","x-min-tier":"free","description":"Returns a paginated list of all 272 Delhi wards with their current IDW-interpolated PM2.5 reading and AQI tier.","operationId":"listWards","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Number of wards to return."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Zero-based offset for pagination."}],"responses":{"200":{"description":"Ward list with current PM2.5.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WardSummary"}},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"total":{"type":"integer","example":272},"limit":{"type":"integer","example":50},"offset":{"type":"integer","example":0},"has_more":{"type":"boolean","example":true}}},"error":{"nullable":true,"example":null}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"429":{"description":"Monthly quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotaError"}}}}}}},"/v1/wards/{wardId}/current":{"get":{"tags":["Wards"],"summary":"Current reading for a ward","x-min-tier":"free","description":"Returns the latest IDW-interpolated PM2.5 reading for the specified ward, including a staleness timestamp so callers can decide whether data is actionable.","operationId":"getWardCurrent","parameters":[{"name":"wardId","in":"path","required":true,"schema":{"type":"string"},"example":"W-042"}],"responses":{"200":{"description":"Current reading.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"ward_id":{"type":"string"},"name":{"type":"string"},"district":{"type":"string"},"pm25":{"type":"number","nullable":true},"tier":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/AqiTier"}]},"unit":{"type":"string","nullable":true},"source":{"type":"string","enum":["live","estimated"],"nullable":true},"measured_at":{"type":"string","format":"date-time","nullable":true},"staleness_seconds":{"type":"integer","nullable":true,"description":"Seconds since the underlying sensor observation was recorded."}}},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"}}},"error":{"nullable":true,"example":null}}},"example":{"data":{"ward_id":"W-042","name":"Karol Bagh","district":"Central Delhi","pm25":87.4,"tier":"moderate","unit":"µg/m³","source":"live","measured_at":"2024-10-15T06:00:00.000Z","staleness_seconds":480},"meta":{"generated_at":"2024-10-15T06:08:00.000Z"},"error":null}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"404":{"description":"Ward not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/wards/{wardId}/forecast":{"get":{"tags":["Wards"],"summary":"72-hour calibrated forecast","x-min-tier":"free","description":"Returns the next 72 hours of calibrated AQI forecasts with 90 % prediction intervals. Each hourly point includes a confidence label.","operationId":"getWardForecast","parameters":[{"name":"wardId","in":"path","required":true,"schema":{"type":"string"},"example":"W-042"},{"name":"pollutants","in":"query","schema":{"type":"string","default":"pm25"},"description":"Comma-separated list of pollutants to return. Supported: `pm25`, `pm10`, `no2`, `o3`."}],"responses":{"200":{"description":"72-hour forecast.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"ward_id":{"type":"string"},"name":{"type":"string"},"district":{"type":"string"},"forecasts":{"type":"object","description":"Keyed by pollutant param (e.g. `pm25`).","additionalProperties":{"type":"object","properties":{"unit":{"type":"string","example":"µg/m³"},"coverage":{"type":"object","description":"Coverage and issuance provenance for this single forecast vintage.","properties":{"status":{"type":"string","enum":["complete","partial","abstained"]},"expected_points":{"type":"integer","example":72},"available_points":{"type":"integer","example":72},"issued_at":{"type":"string","format":"date-time","nullable":true}}},"points":{"type":"array","items":{"$ref":"#/components/schemas/ForecastPoint"}}}}}}},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"issued_at":{"type":"string","format":"date-time","nullable":true},"model_trained_at":{"type":"string","format":"date-time","nullable":true},"horizon_hours":{"type":"integer","example":72},"pollutants":{"type":"array","items":{"type":"string"}},"issuance_provenance":{"type":"object","additionalProperties":{"type":"object","properties":{"status":{"type":"string","enum":["complete","partial","abstained"]},"expected_points":{"type":"integer"},"available_points":{"type":"integer"},"issued_at":{"type":"string","format":"date-time","nullable":true}}}}}},"error":{"nullable":true,"example":null}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"404":{"description":"Ward not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Forecast temporarily unavailable (model not yet run).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/wards/{wardId}/ventilation-windows":{"get":{"tags":["Wards"],"summary":"Ventilation windows for a ward","x-min-tier":"free","description":"Segments the next N forecast hours into contiguous blocks where PM2.5 is below a health-profile threshold. Also returns all hourly points so callers can build their own UI.","operationId":"getVentilationWindows","parameters":[{"name":"wardId","in":"path","required":true,"schema":{"type":"string"},"example":"W-042"},{"name":"hours","in":"query","schema":{"type":"integer","minimum":1,"maximum":168,"default":48},"description":"Number of forecast hours to scan."},{"name":"profile","in":"query","schema":{"type":"string","enum":["general","child","elderly","asthma","outdoor_worker"],"default":"general"},"description":"Health profile — sensitive profiles use stricter PM2.5 ceilings."},{"name":"activity","in":"query","schema":{"type":"string","enum":["run","walk","cycle","commute"],"default":"walk"},"description":"Activity type — vigorous activities use stricter thresholds."}],"responses":{"200":{"description":"Ventilation windows and hourly forecast points.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"ward_id":{"type":"string"},"name":{"type":"string"},"district":{"type":"string"},"pm25_threshold_ugm3":{"type":"number","description":"Effective PM2.5 ceiling applied (strictest of profile + activity thresholds)."},"profile":{"type":"string"},"activity":{"type":"string"},"ventilation_windows":{"type":"array","description":"Contiguous below-threshold blocks.","items":{"$ref":"#/components/schemas/VentilationWindow"}},"hourly_points":{"type":"array","description":"All hourly forecast points in the scanned window with below_threshold flag.","items":{"$ref":"#/components/schemas/HourPoint"}},"current_ventilation_index_m2s":{"type":"number","nullable":true,"description":"Current ventilation index (BLH × wind speed in m²/s). Higher = better dispersion."}}},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"issued_at":{"type":"string","format":"date-time","description":"Timestamp of the forecast issuance used."},"horizon_hours":{"type":"integer","description":"Hours scanned."},"window_count":{"type":"integer","description":"Number of ventilation windows found."},"note":{"type":"string","description":"Human-readable summary of the result."}}},"error":{"nullable":true,"example":null}}},"example":{"data":{"ward_id":"W-042","name":"Karol Bagh","district":"Central Delhi","pm25_threshold_ugm3":60,"profile":"general","activity":"walk","ventilation_windows":[{"start_at":"2024-10-15T05:00:00.000Z","end_at":"2024-10-15T09:00:00.000Z","duration_hours":4,"mean_pm25":28.3,"peak_pm25":32.1,"tier":"good"}],"hourly_points":[{"time":"2024-10-15T05:00:00.000Z","pm25":28.3,"pm25_low":22.1,"pm25_high":35.4,"tier":"good","below_threshold":true}],"current_ventilation_index_m2s":1240.5},"meta":{"generated_at":"2024-10-15T06:30:00.000Z","issued_at":"2024-10-15T06:00:00.000Z","horizon_hours":48,"window_count":1,"note":"1 window(s) found where PM2.5 ≤ 60 µg/m³."},"error":null}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"404":{"description":"Ward not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Forecast temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/delhi/smoke":{"get":{"tags":["Delhi"],"summary":"Smoke trajectory","x-min-tier":"free","description":"Returns the current smoke trajectory for Delhi: upwind fire count, fire cluster location, wind vector, estimated PM2.5 contribution (`none`/`low`/`moderate`/`high`), and a best-estimate arrival window. Data sourced from NASA FIRMS VIIRS and Open-Meteo.","operationId":"getDelhiSmoke","responses":{"200":{"description":"Smoke trajectory.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"fire_count_24h":{"type":"integer"},"total_frp_mw":{"type":"number","nullable":true},"mean_frp_mw":{"type":"number","nullable":true},"cluster_lat":{"type":"number","nullable":true},"cluster_lon":{"type":"number","nullable":true},"distance_km":{"type":"number","nullable":true},"origin_region":{"type":"string","nullable":true},"wind_dir_deg":{"type":"number","nullable":true},"wind_speed_ms":{"type":"number","nullable":true},"wind_aligned":{"type":"boolean"},"pm25_contribution":{"type":"string","enum":["none","low","moderate","high"]},"arrival_window":{"nullable":true,"type":"object","properties":{"start_at":{"type":"string","format":"date-time"},"end_at":{"type":"string","format":"date-time"},"transit_hours":{"type":"number"}}},"upwind_arc_deg":{"type":"array","items":{"type":"number"}},"confidence":{"type":"string","enum":["high","medium","low"]}}},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"fire_data_source":{"type":"string"},"met_data_source":{"type":"string"},"lookback_hours":{"type":"integer"}}},"error":{"nullable":true,"example":null}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}}}}},"/v1/delhi/sources":{"get":{"tags":["Delhi"],"summary":"Source attribution","x-min-tier":"free","description":"Returns CAQM-derived source attribution fractions for Delhi on a given date: how much of the PM2.5 load comes from vehicles, stubble burning, industry, dust, cooking, etc. Based on static seasonal priors from the CAQM Unified Source Apportionment Study (2022).","operationId":"getDelhiSources","parameters":[{"name":"date","in":"query","schema":{"type":"string","format":"date"},"description":"Calendar date in IST (YYYY-MM-DD). Defaults to today. May not be more than 7 days in the future.","example":"2024-10-15"}],"responses":{"200":{"description":"Source attribution fractions.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"date":{"type":"string"},"season":{"type":"string"},"season_label":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"sector":{"type":"string"},"fraction":{"type":"number"},"percent":{"type":"number"}}}},"mode":{"type":"string","enum":["seasonal_prior"]}}},"meta":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"data_source":{"type":"string"},"scope":{"type":"string"},"note":{"type":"string"}}},"error":{"nullable":true,"example":null}}},"example":{"data":{"date":"2024-10-15","season":"post_monsoon","season_label":"Post-Monsoon (Oct–Nov)","sources":[{"sector":"stubble_burning","fraction":0.29,"percent":29},{"sector":"vehicles","fraction":0.23,"percent":23},{"sector":"industry","fraction":0.18,"percent":18},{"sector":"dust","fraction":0.16,"percent":16},{"sector":"cooking","fraction":0.09,"percent":9},{"sector":"other","fraction":0.05,"percent":5}],"mode":"seasonal_prior"},"meta":{"generated_at":"2024-10-15T06:30:00.000Z","data_source":"CAQM Unified Source Apportionment Study (2022)","scope":"Delhi-NCR city-level seasonal average","note":"Fractions are static seasonal priors, not real-time modelled attribution."},"error":null}}}},"400":{"description":"Invalid or out-of-range date.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}}}}},"/seismic/events":{"get":{"tags":["Seismic"],"summary":"List recent global earthquake events","security":[],"description":"Returns recent global earthquakes from USGS, EMSC, GEOFON, GeoNet, AusPass, and ISC. Real-time (EMSC WebSocket + USGS polling every 5 min). Supports magnitude, zone, and time filters.","operationId":"listSeismicEvents","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":50},"description":"Max events to return."},{"name":"minMag","in":"query","schema":{"type":"number","format":"float"},"description":"Minimum magnitude filter, e.g. 4.5"},{"name":"maxMag","in":"query","schema":{"type":"number","format":"float"},"description":"Maximum magnitude filter."},{"name":"zone","in":"query","schema":{"type":"string"},"description":"Filter by tectonic zone ID, e.g. himalayan_arc"},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO-8601 UTC start time."},{"name":"until","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO-8601 UTC end time."},{"name":"centerLat","in":"query","schema":{"type":"number","minimum":-90,"maximum":90},"description":"Supply with centerLon and radiusKm to filter by exact great-circle distance before applying limit."},{"name":"centerLon","in":"query","schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"radiusKm","in":"query","schema":{"type":"number","minimum":1,"maximum":2000},"description":"Requires centerLat and centerLon; maximum search radius is 2000 km."},{"name":"source","in":"query","schema":{"type":"string","enum":["usgs","emsc","geofon","geonet","auspass","isc"]},"description":"Filter by source network."}],"responses":{"200":{"description":"Earthquake event list.","content":{"application/json":{"schema":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"total":{"type":"integer","description":"Total matching events (unpaged)."},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"emsc-20260729_0000281"},"usgsId":{"type":"string","nullable":true},"emscId":{"type":"string","nullable":true},"geofonId":{"type":"string","nullable":true},"time":{"type":"string","format":"date-time","description":"UTC observation time."},"lat":{"type":"number"},"lon":{"type":"number"},"depthKm":{"type":"number"},"magnitude":{"type":"number"},"magType":{"type":"string","example":"ml"},"place":{"type":"string"},"tsunamiFlag":{"type":"boolean"},"networkConfirmations":{"type":"integer"},"alertIssued":{"type":"boolean"},"magnitudeTier":{"type":"string","enum":["minor","light","moderate","strong","major","great"]},"hasForecast":{"type":"boolean","description":"Must be true before calling /seismic/forecast/{eventId}."},"clusterId":{"type":"string","nullable":true,"description":"Non-null if part of a tracked aftershock sequence."},"source":{"type":"string"}}}}}}}}}}}},"/seismic/zones":{"get":{"tags":["Seismic"],"summary":"Tectonic zones with ML anomaly scores","security":[],"description":"Returns all monitored tectonic zones with their ML-scored anomaly state, rate ratios, and swarm scores. Cached 10 minutes.","operationId":"listSeismicZones","responses":{"200":{"description":"Zone list.","content":{"application/json":{"schema":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"zones":{"type":"array","items":{"type":"object","properties":{"zoneId":{"type":"string"},"name":{"type":"string"},"tectonicType":{"type":"string"},"tectonicTypeLabel":{"type":"string"},"mlAnomalyScore":{"type":"number","nullable":true,"description":"Signed float; positive = above-average activity."},"mlIsAnomaly":{"type":"boolean"},"mlRateRatio7d":{"type":"number","nullable":true},"mlSwarmScore":{"type":"number","nullable":true},"tecAnomalyActive":{"type":"boolean"},"bboxMinLat":{"type":"number"},"bboxMaxLat":{"type":"number"},"bboxMinLon":{"type":"number"},"bboxMaxLon":{"type":"number"},"nearbyCities":{"type":"array","items":{"type":"string"}}}}}}}}}}}}},"/seismic/status":{"get":{"tags":["Seismic"],"summary":"Seismic feed and ML pipeline status","security":[],"description":"Returns the connectivity status of all seismic ingest feeds and the state of ML pipelines (declustering, escalation training, escalation scoring). Note: this endpoint aggregates live DB queries and may take 3–4 s.","operationId":"getSeismicStatus","responses":{"200":{"description":"Feed and pipeline status.","content":{"application/json":{"schema":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"emscWebSocketStatus":{"type":"string","enum":["connected","disconnected","reconnecting"]},"event24hCount":{"type":"integer"},"feeds":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["healthy","degraded","down"]},"lastPolledAt":{"type":"string","format":"date-time","nullable":true},"message":{"type":"string"}}}},"mlPipelines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["healthy","degraded","down"]},"lastPolledAt":{"type":"string","nullable":true},"message":{"type":"string"}}}}}}}}}}}},"/seismic/forecast/{eventId}":{"get":{"tags":["Seismic"],"summary":"ML escalation forecast for an event","security":[],"description":"Returns the ML escalation probability forecast for a specific event. Only available when hasForecast=true on the event. Returns 404 otherwise.","operationId":"getSeismicForecast","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"emsc-20260729_0000281","description":"Canonical event ID from /seismic/events. Always check hasForecast=true before calling."}],"responses":{"200":{"description":"Escalation forecast."},"404":{"description":"No forecast available for this event (hasForecast=false)."}}}},"/seawatch/conditions":{"get":{"tags":["Marine"],"summary":"Ocean conditions for monitored coastal cities","security":[],"description":"Returns wave height, swell, SST, storm surge, and current speed for all monitored coastal cities. Sourced from Copernicus Marine + Open-Meteo Marine. Cached 5 minutes.","operationId":"getMarineConditions","responses":{"200":{"description":"City ocean conditions.","content":{"application/json":{"schema":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"cities":{"type":"array","items":{"type":"object","properties":{"city":{"type":"string"},"lat":{"type":"number"},"lon":{"type":"number"},"metrics":{"type":"object","description":"Each key is a metric slug. Value shape: { value: number, unit: string, measuredAt: date-time }","additionalProperties":{"type":"object","properties":{"value":{"type":"number"},"unit":{"type":"string"},"measuredAt":{"type":"string","format":"date-time"}}}}}}},"provenance":{"type":"object","properties":{"validTime":{"type":"string","format":"date-time"},"availabilityTime":{"type":"string","format":"date-time"},"uncertaintyLabel":{"type":"string","enum":["low","medium","high"]},"sources":{"type":"array","items":{"type":"object"}}}}}}}}}}}},"/seawatch/marine-evidence":{"get":{"tags":["Marine"],"summary":"Fresh, aligned Copernicus Marine evidence","security":[],"description":"Returns bounded Copernicus Marine SST, current, and chlorophyll samples with product provenance. Missing, delayed, inaccessible, or stale products remain unavailable; no synthetic fallback is used.","operationId":"getMarineEvidence","responses":{"200":{"description":"Copernicus Marine evidence envelope.","content":{"application/json":{"schema":{"type":"object","required":["generatedAt","coverage","available","products","points"],"properties":{"generatedAt":{"type":"string","format":"date-time"},"coverage":{"type":"string","enum":["full","partial","none"]},"available":{"type":"boolean"},"issueTime":{"type":"string","format":"date-time","nullable":true},"ingestedAt":{"type":"string","format":"date-time","nullable":true},"staleAfterHours":{"type":"number"},"products":{"type":"array","items":{"type":"object","additionalProperties":true}},"alignment":{"type":"object","nullable":true,"additionalProperties":true},"limitations":{"type":"array","items":{"type":"string"}},"points":{"type":"array","items":{"type":"object","additionalProperties":true}},"lastValidEvidenceAt":{"type":"string","format":"date-time","nullable":true}}}}}}}}},"/seawatch/alerts":{"get":{"tags":["Marine"],"summary":"Active marine alerts","security":[],"description":"Returns active coastal surge, reef bleaching, and algal bloom alerts. Returns HTTP 200 with empty alerts array when no alerts are active — not an error.","operationId":"listMarineAlerts","responses":{"200":{"description":"Marine alert list (may be empty).","content":{"application/json":{"schema":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"alerts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"alertType":{"type":"string"},"region":{"type":"string"},"severity":{"type":"string"},"issuedAt":{"type":"string","format":"date-time"},"resolvedAt":{"type":"string","format":"date-time","nullable":true},"lat":{"type":"number"},"lon":{"type":"number"},"source":{"type":"string"},"metadata":{"type":"object"}}}}}}}}}}}},"/seawatch/scenes":{"get":{"tags":["Marine"],"summary":"Satellite marine scenes","security":[],"description":"Returns satellite-derived reef risk, chlorophyll, SST, and haze scenes. Returns HTTP 200 with empty scenes array when no recent satellite pass has been processed.","operationId":"listMarineScenes","responses":{"200":{"description":"Marine scene list (may be empty)."}}}},"/agro/regions":{"get":{"tags":["Agriculture"],"summary":"All agricultural regions","security":[],"description":"Returns all 7 monitored global agricultural regions with current average NDVI and stressed fraction. Cached 5 minutes.","operationId":"listAgroRegions","responses":{"200":{"description":"Region list.","content":{"application/json":{"schema":{"type":"object","properties":{"regions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["igp","us_midwest","sahel","cerrado","ukraine","mekong","murray_darling","el_salvador"]},"name":{"type":"string"},"description":{"type":"string"},"bbox":{"type":"array","items":{"type":"number"}},"dominantCrops":{"type":"array","items":{"type":"string"}},"avgNdvi":{"type":"number","nullable":true},"stressedFraction":{"type":"number","nullable":true},"districtCount":{"type":"integer"},"dataSource":{"type":"string"}}}}}}}}}}}},"/agro/regions/{regionKey}/summary":{"get":{"tags":["Agriculture"],"summary":"Detailed region summary","security":[],"description":"Returns crop stage breakdown, stress breakdown, and burn activity for one agricultural region. regionKey must be one of: igp, us_midwest, sahel, cerrado, ukraine, mekong, murray_darling, el_salvador.","operationId":"getAgroRegionSummary","parameters":[{"name":"regionKey","in":"path","required":true,"schema":{"type":"string","enum":["igp","us_midwest","sahel","cerrado","ukraine","mekong","murray_darling","el_salvador"]},"description":"Region key. Short aliases (usm, cer, etc.) return 404."}],"responses":{"200":{"description":"Region summary."},"404":{"description":"Unknown regionKey."}}}},"/agro/districts":{"get":{"tags":["Agriculture"],"summary":"Districts GeoJSON","security":[],"description":"Returns a GeoJSON FeatureCollection of districts in a region with per-district NDVI, stress, phenology stage, and dominant crop.","operationId":"listAgroDistricts","parameters":[{"name":"region","in":"query","required":true,"schema":{"type":"string","enum":["igp","us_midwest","sahel","cerrado","ukraine","mekong","murray_darling","el_salvador"]},"description":"Region key."}],"responses":{"200":{"description":"GeoJSON FeatureCollection of districts.","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","example":"FeatureCollection"},"features":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"Feature"},"geometry":{"type":"object"},"properties":{"type":"object","properties":{"districtId":{"type":"string","example":"igp_meerut"},"districtName":{"type":"string"},"regionKey":{"type":"string"},"ndvi":{"type":"number","nullable":true},"ndre":{"type":"number","nullable":true},"stressedFraction":{"type":"number","nullable":true},"stressType":{"type":"string","nullable":true},"phenologyStage":{"type":"string","nullable":true},"dominantCrop":{"type":"string","nullable":true},"lastObserved":{"type":"string","format":"date-time","nullable":true},"dataSource":{"type":"string"}}}}}}}}}}}}}},"/urban/cities":{"get":{"tags":["Urban"],"summary":"Monitored urban cities","security":[],"description":"Returns the list of monitored cities with city slugs used as the city parameter in other urban endpoints. Cached 10 minutes.","operationId":"listUrbanCities","responses":{"200":{"description":"City list.","content":{"application/json":{"schema":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"cities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"delhi","description":"Use this as the city slug in other urban endpoints."},"displayName":{"type":"string"},"country":{"type":"string"},"centroid":{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"bbox":{"type":"object"},"sceneCount":{"type":"integer"},"lastPassDate":{"type":"string","format":"date-time","nullable":true},"dominantChangeSignal":{"type":"string","nullable":true}}}}}}}}}}}},"/urban/cities/{cityId}/uhi-forecast":{"get":{"tags":["Urban"],"summary":"Seven-day urban heat-island forecast","security":[],"description":"Projects district/city-scale surface UHI anomaly from Open-Meteo weather and satellite-informed urban morphology. This is a screening transition model, not building-level simulation.","operationId":"getUrbanUhiForecast","parameters":[{"name":"cityId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Seven-day UHI forecast with state vector, risk component, and meteorological assumptions."},"404":{"description":"Unknown city."}}}},"/urban/cities/{cityId}/interventions":{"post":{"tags":["Urban"],"summary":"Simulate green infrastructure cooling","security":[],"description":"Returns baseline and intervention UHI series, confidence bands, before/after anomaly grids, and forward heat-stress risk for a 30–365 day horizon.","operationId":"simulateUrbanIntervention","parameters":[{"name":"cityId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["intervention_type","magnitude","horizon_days"],"properties":{"intervention_type":{"type":"string","enum":["tree_cover","albedo","water_bodies"]},"magnitude":{"type":"number","description":"Percentage points for tree/water cover, or albedo points for reflective surfaces."},"horizon_days":{"type":"integer","minimum":30,"maximum":365,"default":90}}}}}},"responses":{"200":{"description":"Intervention simulation with impact, uncertainty, and risk adjustment."},"400":{"description":"Invalid intervention request."},"404":{"description":"Unknown city."}}}},"/urban/change-summary":{"get":{"tags":["Urban"],"summary":"Urban satellite change summary","security":[],"description":"Returns satellite-derived land cover change passes for a city. Cached 30 minutes.","operationId":"getUrbanChangeSummary","parameters":[{"name":"city","in":"query","required":true,"schema":{"type":"string"},"description":"City slug from /urban/cities, e.g. delhi."}],"responses":{"200":{"description":"Change summary."},"404":{"description":"Unknown city slug — fetch valid slugs from /urban/cities first."}}}},"/compound-risk/active":{"get":{"tags":["CompoundRisk"],"summary":"Active cross-domain compound risk events","security":[],"description":"Returns currently active compound risk events (e.g. heat+air, flood+disease, fire+smoke). Returns HTTP 200 with empty events[] when no events match — not an error. Always pass ?domain= to filter to relevant events.","operationId":"listCompoundRiskActive","parameters":[{"name":"domain","in":"query","schema":{"type":"string","enum":["air","earth","sea","agro","urban"]},"description":"Filter to events where primaryDomain or secondaryDomain matches. Strongly recommended to avoid cross-domain noise."}],"responses":{"200":{"description":"Active compound risk events (may be empty).","content":{"application/json":{"schema":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"count":{"type":"integer"},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"riskType":{"type":"string"},"primaryDomain":{"type":"string"},"secondaryDomain":{"type":"string","nullable":true},"description":{"type":"string"},"severity":{"type":"string","enum":["watch","advisory","alert","critical"]},"startedAt":{"type":"string","format":"date-time","nullable":true},"expiresAt":{"type":"string","format":"date-time","nullable":true},"affectedRegions":{"type":"array","items":{"type":"string"}},"fingerprint":{"type":"string"}}}}}}}}}}}},"/compound-risk/history":{"get":{"tags":["CompoundRisk"],"summary":"Historical compound risk events","security":[],"description":"Returns resolved compound risk events within a lookback window. Default 90 days, max 365.","operationId":"listCompoundRiskHistory","parameters":[{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":90},"description":"Lookback window in days."}],"responses":{"200":{"description":"Historical events list."}}}},"/data-health":{"get":{"tags":["DataHealth"],"summary":"Platform data source health","security":[],"description":"Returns freshness and status for all platform data feeds. groundCoverage='estimated' means all independent Delhi ground PM2.5 monitors are stale — air readings are CAMS reanalysis only. Cached 60 seconds. Call in parallel with other endpoints; re-query at most every 60 s.","operationId":"getDataHealth","parameters":[{"name":"at","in":"query","schema":{"type":"string","format":"date-time"},"description":"Optional ISO-8601 UTC timestamp for a historical health snapshot."}],"responses":{"200":{"description":"Platform data health.","content":{"application/json":{"schema":{"type":"object","properties":{"overall":{"type":"string","enum":["healthy","degraded","stale","down","unknown"]},"generatedAt":{"type":"string","format":"date-time"},"groundCoverage":{"type":"string","enum":["live","estimated"],"description":"live = ≥1 independent Delhi ground PM2.5 monitor fresh; estimated = CAMS reanalysis only."},"feeds":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["healthy","degraded","stale","down","optional","unsupported","partial","unknown"]},"lastUpdated":{"type":"string","format":"date-time","nullable":true},"ageMinutes":{"type":"number","nullable":true},"expectedCadenceMinutes":{"type":"number"},"message":{"type":"string"},"fallback":{"type":"string","description":"What happens in the UI/model when this feed is down."},"uptime24h":{"type":"number","nullable":true}}}}}}}}}}}}}}