{"openapi":"3.1.0","info":{"title":"OpenGrid Hub","description":"The OpenGrid Hub API. A registry for grid data, assumptions and models, and a\ncontrol plane for finding the datasets behind them.\n\n**Whether this API returns data depends on custody.** For a dataset hosted\nelsewhere it returns metadata and an access plan saying where the data is and\nhow to read it — `/download` is a redirect to the source, `/access-plan` is a\ndocument, and nothing is proxied. For an object *registered* with the Hub — a\nmodel, an assumption set, a study filing, a reference network — the Hub holds\nthe bytes and serves them, because an immutable citable release has to still\nbe there when somebody follows the citation.\n\n**Absent means \"not captured\", never \"no source\".** A field missing from a\nrecord is a gap in what has been catalogued, not a statement that the dataset\nlacks it. Completeness levels say how much of a record has been filled in, and\nthe three quality facets are graded independently and never combined.\n","version":"1.0.0"},"paths":{"/v1/datasets":{"get":{"tags":["datasets"],"summary":"Search, filter, facet and paginate the catalog","description":"Search the catalog.\n\nSearch-while-typing is the intended interaction (PRD §F3), so the last token\nof ``q`` is prefix-expanded and there is no submit step. Facets come back\nwith the results rather than from a second call: a UI that had to ask twice\nwould show counts that disagree with the list for as long as the second\ncall is in flight.","operationId":"search_datasets_v1_datasets_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text. Prefix-matched on the last token.","title":"Q"},"description":"Free text. Prefix-matched on the last token."},{"name":"record_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"dataset or reference_model.","title":"Record Type"},"description":"dataset or reference_model."},{"name":"fidelity_class","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Reference models only: indicative, screening or authoritative.","title":"Fidelity Class"},"description":"Reference models only: indicative, screening or authoritative."},{"name":"data_domain","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"DD1-DD10, or the concept IRI.","title":"Data Domain"},"description":"DD1-DD10, or the concept IRI."},{"name":"provenance_class","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Provenance Class"}},{"name":"license","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"SPDX id or LicenseRef.","title":"License"},"description":"SPDX id or LicenseRef."},{"name":"concept","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Concept IRI carried by a field of the dataset.","title":"Concept"},"description":"Concept IRI carried by a field of the dataset."},{"name":"spatial_granularity","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Spatial Granularity"}},{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Distribution format label.","title":"Format"},"description":"Distribution format label."},{"name":"completeness_level","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Completeness Level"}},{"name":"anonymous_access","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Anonymous Access"}},{"name":"field_count_bucket","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"How much of the schema is described: none, 1-9, 10-49, 50+.","title":"Field Count Bucket"},"description":"How much of the schema is described: none, 1-9, 10-49, 50+."},{"name":"access_restriction","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Access Restriction"}},{"name":"review_state","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Review State"}},{"name":"harvest_source","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"How the record got here — see #85.","title":"Harvest Source"},"description":"How the record got here — see #85."},{"name":"supported_analysis","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Analysis-type concept IRI the dataset supports.","title":"Supported Analysis"},"description":"Analysis-type concept IRI the dataset supports."},{"name":"voltage_class","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Voltage Class"}},{"name":"time_resolution","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Time Resolution"}},{"name":"update_cadence","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Update Cadence"}},{"name":"link_health","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"verified, degraded, unreachable, redirected.","title":"Link Health"},"description":"verified, degraded, unreachable, redirected."},{"name":"provenance_grade","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"A, B, C or D.","title":"Provenance Grade"},"description":"A, B, C or D."},{"name":"documentation_grade","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"A, B, C or D.","title":"Documentation Grade"},"description":"A, B, C or D."},{"name":"currency_grade","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"A, B or D.","title":"Currency Grade"},"description":"A, B or D."},{"name":"bulk_download","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bulk Download"}},{"name":"reference_only","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Reference Only"}},{"name":"has_usage_evidence","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Usage Evidence"}},{"name":"share_alike","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Whether the licence obliges a derived work to carry the same terms. `false` is the filter an adopter who cannot accept that obligation on their own data actually needs.","title":"Share Alike"},"description":"Whether the licence obliges a derived work to carry the same terms. `false` is the filter an adopter who cannot accept that obligation on their own data actually needs."},{"name":"resolution_max_m","in":"query","required":false,"schema":{"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}],"description":"Keep only datasets whose spatial resolution is this fine or finer, in metres. Records that do not state one are excluded, because 'not captured' is not 'fine enough' — see `spatial_granularity` for the class, which most records do carry.","title":"Resolution Max M"},"description":"Keep only datasets whose spatial resolution is this fine or finer, in metres. Records that do not state one are excluded, because 'not captured' is not 'fine enough' — see `spatial_granularity` for the class, which most records do carry."},{"name":"field_count_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Keep only datasets that describe at least this many fields. `field_count_min=1` is 'show me the datasets I can actually interpret' — the question completeness_level cannot answer, because level 1 means no field metadata by definition and level 2 additionally requires a definition and a value basis on every field, which a schema probe cannot supply.","title":"Field Count Min"},"description":"Keep only datasets that describe at least this many fields. `field_count_min=1` is 'show me the datasets I can actually interpret' — the question completeness_level cannot answer, because level 1 means no field metadata by definition and level 2 additionally requires a definition and a value basis on every field, which a schema probe cannot supply."},{"name":"bbox","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"west,south,east,north in WGS 84.","title":"Bbox"},"description":"west,south,east,north in WGS 84."},{"name":"temporal_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO 8601.","title":"Temporal Start"},"description":"ISO 8601."},{"name":"temporal_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO 8601.","title":"Temporal End"},"description":"ISO 8601."},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated fields; a leading `-` is descending, e.g. `-modified`.","title":"Sort"},"description":"Comma-separated fields; a leading `-` is descending, e.g. `-modified`."},{"name":"facets","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated facet fields.","title":"Facets"},"description":"Comma-separated facet fields."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":0,"default":20,"title":"Limit"}},{"name":"include_unconfirmed","in":"query","required":false,"schema":{"type":"boolean","description":"Stewards only.","default":false,"title":"Include Unconfirmed"},"description":"Stewards only."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponseModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/datasets/{dataset_id}":{"get":{"tags":["datasets"],"summary":"One record","operationId":"get_dataset_v1_datasets__dataset_id__get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it.","examples":["ecmwf-era5"],"title":"Dataset Id"},"description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/datasets/{dataset_id}/schema":{"get":{"tags":["datasets"],"summary":"Field-level metadata","description":"The record's fields, with units and concepts where they resolve.\n\nRead from the graph rather than the index: the index carries a field\n*count* because that is what a list view needs, and this endpoint exists\nfor the caller who wants the fields themselves.\n\nPaged, because a schema is no longer always small. Reading a Zarr store's\nown metadata gives ERA5 273 fields, and a caller that cannot ask for the\nrest of them is told there are more and left unable to see them. `limit`\nis absent by default so an existing caller gets what it always got.","operationId":"get_schema_v1_datasets__dataset_id__schema_get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it.","examples":["ecmwf-era5"],"title":"Dataset Id"},"description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it."},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":1000,"minimum":1},{"type":"null"}],"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SchemaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/datasets/{dataset_id}/quality":{"get":{"tags":["datasets"],"summary":"The three quality facets","description":"Currency, provenance and documentation, graded independently.\n\nThere is deliberately no composite score (ADR-0007). A dataset can be\nperfectly current and completely unprovenanced, and averaging those into\none number destroys the only information a user could act on.","operationId":"get_quality_v1_datasets__dataset_id__quality_get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it.","examples":["ecmwf-era5"],"title":"Dataset Id"},"description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QualityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/datasets/{dataset_id}/distributions":{"get":{"tags":["datasets"],"summary":"Access paths, with capabilities and link health","description":"Every way to get the data, and what is known about each.\n\nRead from the record, not the index: the index carries only enough of a\ndistribution to filter and render a list row, and deliberately no access\nURLs — a search response should not haul every URL in the catalog to a\nclient that wanted ten titles.\n\nUnhealthy paths are included and marked. A dead link a user can see is a\nreportable fact; a dead link silently removed is a dataset that appears to\nhave no access path at all.","operationId":"get_distributions_v1_datasets__dataset_id__distributions_get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it.","examples":["ecmwf-era5"],"title":"Dataset Id"},"description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DistributionDetail"},"title":"Response Get Distributions V1 Datasets  Dataset Id  Distributions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/datasets/{dataset_id}/links":{"get":{"tags":["datasets"],"summary":"Datasets that go with this one, and why","description":"Ranked, explained connections to other catalog records (PRD §F6).\n\nComputed at request time rather than read from the stored graph, because\nthe candidate set depends on who is asking. Generating candidates through\nthe index with the caller's entitlement compiled in is ADR-0006's rule;\nreading a stored list and filtering it afterwards would be the post-filter\nthe ADR forbids, and would leak the existence of an allow-listed record\nthrough a suggestion that then disappeared.\n\nA correlated pairing is **reduced, never hidden** (PRD §F6.9). A user told\nthat two datasets are related-but-not-independent can act on it; a user\nshown nothing concludes they are unrelated, which is a stronger and more\nwrong claim.","operationId":"get_links_v1_datasets__dataset_id__links_get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it.","examples":["ecmwf-era5"],"title":"Dataset Id"},"description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinksResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/datasets/{dataset_id}/access-plan":{"post":{"tags":["datasets"],"summary":"How to read this dataset. Never the bytes themselves.","description":"Issue an access plan.\n\nOne uniform shape whether the dataset is 800 KB or 4 TB; only the path\ndiffers. Licence, attribution and quality grades travel *in the plan*,\nwhich is what makes agentic access defensible — the guardrail metadata is\nin the payload rather than in a page the agent never read (PRD §F7).\n\nPOST rather than GET because the request carries a slice specification, and\nbecause issuing a plan is an auditable event: PRD §F10 requires grants and\nrefusals to be logged, and §12.9 leaves open whether a plan is revoked when\nan allow-list changes. Both need a row per issue.","operationId":"access_plan_v1_datasets__dataset_id__access_plan_post","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it.","examples":["ecmwf-era5"],"title":"Dataset Id"},"description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AccessPlanRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessPlanResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/datasets/{dataset_id}/download":{"get":{"tags":["datasets"],"summary":"Redirect to the source. The API never serves bytes.","description":"The human-facing path: click, and end up at the source.\n\nA redirect rather than a proxy, and that is a design decision rather than\nan optimisation. Proxying would make OpenGrid an egress bill, a bandwidth\nbottleneck and a party to every licence it does not hold. The redirect also\nmeans the source sees its own traffic, which is what keeps a data publisher\nwilling to be catalogued.","operationId":"download_v1_datasets__dataset_id__download_get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it.","examples":["ecmwf-era5"],"title":"Dataset Id"},"description":"The dataset's slug, which is the last segment of its IRI — `ecmwf-era5` for `https://catalog.opengrid.org/ds/ecmwf-era5`. A caller holding the IRI takes its last segment; a full IRI is not accepted in the path, because its slashes are indistinguishable from the sub-resource paths (`/schema`, `/quality`) that follow it."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"302":{"description":"Redirect to the best available access URL.","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/domains":{"get":{"tags":["concepts"],"summary":"DD1-DD10","description":"The ten data domains, each with its structural note.\n\nOrdered by notation rather than alphabetically, because DD1 through DD10 is\nan ordering the PRD gives them and \"DD10, DD1, DD2\" is nobody's idea of a\nlist of ten things.","operationId":"list_domains_v1_domains_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DomainResponse"},"title":"Response List Domains V1 Domains Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/concepts":{"get":{"tags":["concepts"],"summary":"The SKOS schemes","description":"List concepts. Flat, with a scheme filter and a label search.\n\nNo dataset counts here: this endpoint returns up to a thousand concepts and\ncounting each against the index would be a thousand searches. The count is\non the single-concept endpoint, where it is one search and worth having.","operationId":"list_concepts_v1_concepts_get","parameters":[{"name":"scheme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Restrict to one concept scheme.","title":"Scheme"},"description":"Restrict to one concept scheme."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring match on the label.","title":"Q"},"description":"Substring match on the label."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConceptResponse"},"title":"Response List Concepts V1 Concepts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/concepts/{concept_id}":{"get":{"tags":["concepts"],"summary":"One concept, with its hierarchy, crosswalks and dataset count","operationId":"get_concept_v1_concepts__concept_id__get","parameters":[{"name":"concept_id","in":"path","required":true,"schema":{"type":"string","description":"A concept IRI, or its last segment.","title":"Concept Id"},"description":"A concept IRI, or its last segment."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConceptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/gaps":{"get":{"tags":["gaps"],"summary":"Data requirements with no known open supplier","description":"Search the gap register.\n\nEverything here is a curated finding with a named observer and a date, not\na computation. The register is small and hand-maintained on purpose: a gap\nclaims something about the whole open landscape, which is not a claim to\ngenerate.","operationId":"search_gaps_v1_gaps_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, matched against the title, category and reason.","title":"Q"},"description":"Free text, matched against the title, category and reason."},{"name":"data_domain","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"DD1-DD10.","title":"Data Domain"},"description":"DD1-DD10."},{"name":"needed_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"An analysis class that needs this, from the analysis-type scheme — capacityExpansion, productionCost, reliabilityAssessment, acPowerFlow.","title":"Needed By"},"description":"An analysis class that needs this, from the analysis-type scheme — capacityExpansion, productionCost, reliabilityAssessment, acPowerFlow."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GapSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/submissions":{"post":{"tags":["intake"],"summary":"Tell us about a dataset we do not have","description":"Accept an intake form.\n\n202 rather than 201: nothing has been created that the submitter can go and\nlook at, and saying \"created\" would imply otherwise. What has happened is\nthat the form is in a queue a human reads.","operationId":"create_submission_v1_submissions_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionReceipt"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reports":{"post":{"tags":["intake"],"summary":"Report a problem with a record, a field or a link","description":"Accept an issue report.\n\nAnonymous is allowed and is the common case: the person who notices that a\ndownload 404s is whoever tried to download it. Requiring an account here\nwould mean the reports that matter most never arrive.","operationId":"create_report_v1_reports_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportReceipt"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/me":{"get":{"tags":["auth"],"summary":"The caller, as the API sees them","description":"Answers honestly for an anonymous caller rather than returning 401.\n\nA client asking \"who am I\" wants to know, and \"nobody\" is an answer. A 401\nhere would make every UI implement a special case for the state it spends\nmost of its time in.","operationId":"me_v1_auth_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/providers":{"get":{"tags":["auth"],"summary":"Enabled sign-in providers","description":"What a sign-in page should offer.\n\nOnly the configured ones. Rendering a Google button on a deployment with no\nGoogle client id produces an error page that blames the user.","operationId":"providers_v1_auth_providers_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderList"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/login/{provider}":{"get":{"tags":["auth"],"summary":"Begin a federated sign-in","description":"Authorization Code with PKCE.\n\n``next`` is validated against the configured origins before it is stored.\nAn unchecked ``next`` is an open redirect: a link that goes to our sign-in\nand lands on somebody else's page, wearing our domain in the address bar\nfor the part that matters.","operationId":"login_v1_auth_login__provider__get","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}},{"name":"next","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"302":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/callback":{"get":{"tags":["auth"],"summary":"Finish a federated sign-in","operationId":"callback_v1_auth_callback_get","parameters":[{"name":"state","in":"query","required":true,"schema":{"type":"string","title":"State"}},{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"302":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/logout":{"post":{"tags":["auth"],"summary":"End this session","description":"Revoke server-side and clear the cookie.\n\nBoth: clearing only the cookie leaves a session id that still works for\nanyone who copied it, which is exactly the case someone logs out to\nprevent.","operationId":"logout_v1_auth_logout_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/logout-everywhere":{"post":{"tags":["auth"],"summary":"End every session for this user","description":"What a person clicks after losing a laptop.","operationId":"logout_everywhere_v1_auth_logout_everywhere_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/tokens":{"get":{"tags":["auth"],"summary":"Your tokens","operationId":"list_tokens_v1_auth_tokens_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TokenSummary"},"title":"Response List Tokens V1 Auth Tokens Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["auth"],"summary":"Issue a token. The only time you will see it.","description":"Issue a personal access token, within the caller's own permissions.\n\nA scope the user's role does not carry is refused rather than dropped. A\nsilently narrowed token is the worst outcome available: the holder believes\nthey have a working credential, every call fails in a way that looks like a\nbug, and nothing says why.","operationId":"create_token_v1_auth_tokens_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/tokens/{token_id}":{"delete":{"tags":["auth"],"summary":"Revoke a token, permanently","description":"No un-revoke. A token someone revoked because they think it leaked must\nstay dead, and an undo button is a way to reinstate a compromised\ncredential by accident.","operationId":"revoke_token_v1_auth_tokens__token_id__delete","parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/allowlists/{dataset_id}":{"get":{"tags":["allowlists"],"summary":"Who may see this dataset. Custodian only.","operationId":"get_allowlist_v1_allowlists__dataset_id__get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug.","title":"Dataset Id"},"description":"The dataset's slug."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllowlistResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["allowlists"],"summary":"Replace the allow-list. Custodian only.","description":"Replace the whole list.\n\nRevocations happen before grants. If both orders were possible, replacing a\nlist that grants and revokes the same principal would depend on dict\nordering — and the safe resolution of that ambiguity is \"revoked\", not\n\"granted\".","operationId":"put_allowlist_v1_allowlists__dataset_id__put","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","description":"The dataset's slug.","title":"Dataset Id"},"description":"The dataset's slug."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllowlistUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllowlistResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/review":{"get":{"tags":["review"],"summary":"Records awaiting review","description":"The next batch, highest leverage first.","operationId":"queue_v1_review_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"type":"string","description":"draft, in-review, confirmed or flagged.","default":"draft","title":"State"},"description":"draft, in-review, confirmed or flagged."},{"name":"data_domain","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Domain"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewQueueResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/review/{dataset_id}/confirm":{"post":{"tags":["review"],"summary":"Confirm a record, and the fields you checked","description":"Mark a record reviewed.\n\n``confirmed_fields`` is a union with whatever was confirmed before, not a\nreplacement: a second review confirming three more fields must not\nun-confirm the first review's work, and a steward who reviewed one tab\nshould not have to re-check the others to avoid losing them.","operationId":"confirm_v1_review__dataset_id__confirm_post","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewConfirm"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/health":{"get":{"tags":["service"],"summary":"Liveness","description":"Is the process up. Nothing else.\n\nDeliberately touches no dependency: a liveness probe that checked the\ndatabase would restart the API every time the database blinked, and\nrestarting the API does not fix a database.","operationId":"health_v1_health_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/health/ready":{"get":{"tags":["service"],"summary":"Readiness","description":"Can this instance serve requests, and how well.\n\n``unhealthy`` only when the graph is unreachable, because without it there\nis no catalog. A missing index or an unreachable database is ``degraded``:\nsearch falls back, writes fail, reads still work — and a deployment removed\nfrom rotation for a degraded dependency turns a partial outage into a total\none.","operationId":"ready_v1_health_ready_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/health/status":{"get":{"tags":["service"],"summary":"Data state","description":"What is loaded, what is indexed, how far behind the index is.\n\nThe projector lag is the number that matters here: the index is derived\nstate, and a lag that grows without bound means a confirmed record change\nis not reaching search — which looks to a user exactly like the change\nnever happened.","operationId":"status_v1_health_status_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AccessPlanRequest":{"properties":{"distribution_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Distribution Id","description":"Pin a specific access path. Omit and the broker chooses, and says why."},"time_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time Start","description":"ISO 8601."},"time_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time End"},"bbox":{"anyOf":[{"items":{"type":"number"},"type":"array","maxItems":4,"minItems":4},{"type":"null"}],"title":"Bbox","description":"west, south, east, north in WGS 84."},"variables":{"items":{"type":"string"},"type":"array","title":"Variables"}},"additionalProperties":false,"type":"object","title":"AccessPlanRequest","description":"What the caller wants, if anything narrower than everything."},"AccessPlanResponse":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"distribution_id":{"type":"string","title":"Distribution Id"},"mode":{"type":"string","enum":["redirect","partial-read","subsetting-protocol"],"title":"Mode"},"location":{"type":"string","title":"Location"},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format"},"read_instructions":{"additionalProperties":true,"type":"object","title":"Read Instructions"},"requested_slice":{"additionalProperties":true,"type":"object","title":"Requested Slice"},"byte_ranges":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Byte Ranges"},"credentials":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Credentials"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"license":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License"},"license_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Note"},"attribution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attribution"},"redistribution_allowed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Redistribution Allowed","description":"null means not recorded, never 'permitted'. Absent an explicit grant, default copyright applies."},"commercial_use_allowed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Commercial Use Allowed"},"quality_grades":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Quality Grades"},"path_rationale":{"type":"string","title":"Path Rationale","description":"Why this path and not another. Derived from metadata, not configured."},"partial_read_unavailable_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Partial Read Unavailable Reason","description":"Why no partial read is on offer. An absent partial-read section is ambiguous — it looks the same whether the dataset cannot do it or nobody recorded that it can."},"fallback_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fallback Reason"},"caveats":{"items":{"type":"string"},"type":"array","title":"Caveats"}},"additionalProperties":false,"type":"object","required":["dataset_id","distribution_id","mode","location","path_rationale"],"title":"AccessPlanResponse","description":"One uniform shape regardless of whether the dataset is 800 KB or 4 TB.\n\nLicence, attribution and quality grades travel with the plan. That is the\nwhole point of the object (PRD §F7): an agent handed a URL cannot know it\nmay not redistribute what it downloads, and an agent handed a plan is told\nin a field it cannot miss."},"AllowlistEntryModel":{"properties":{"principal_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Principal Id"},"principal_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Principal Email"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"additionalProperties":false,"type":"object","title":"AllowlistEntryModel"},"AllowlistResponse":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"entries":{"items":{"$ref":"#/components/schemas/AllowlistEntryModel"},"type":"array","title":"Entries"},"managed_by":{"type":"string","title":"Managed By","default":"The dataset's custodian. OpenGrid stores and enforces this list and never arbitrates its contents."}},"additionalProperties":false,"type":"object","required":["dataset_id"],"title":"AllowlistResponse"},"AllowlistUpdate":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/AllowlistEntryModel"},"type":"array","title":"Entries"}},"additionalProperties":false,"type":"object","title":"AllowlistUpdate","description":"The whole list, not a patch.\n\nA PUT of the complete set, because a diff-based API makes \"who can see this\"\na question you answer by replaying a history — and the one question a\ncustodian actually asks is \"who is on it right now\"."},"ConceptRef":{"properties":{"iri":{"type":"string","title":"Iri"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"notation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notation"},"definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Definition"}},"type":"object","required":["iri"],"title":"ConceptRef","description":"A SKOS concept as carried in the index: IRI plus its display label."},"ConceptResponse":{"properties":{"iri":{"type":"string","title":"Iri"},"label":{"type":"string","title":"Label"},"definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Definition"},"notation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notation"},"scheme":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scheme"},"broader":{"items":{"$ref":"#/components/schemas/ConceptRef"},"type":"array","title":"Broader"},"narrower":{"items":{"$ref":"#/components/schemas/ConceptRef"},"type":"array","title":"Narrower"},"alt_labels":{"items":{"type":"string"},"type":"array","title":"Alt Labels"},"default_unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Unit"},"unit_symbol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit Symbol"},"external_matches":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"External Matches","description":"Crosswalk targets by scheme, with the match strength as the key."},"dataset_count":{"type":"integer","title":"Dataset Count","default":0}},"additionalProperties":false,"type":"object","required":["iri","label"],"title":"ConceptResponse"},"DataGapModel":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"domain":{"type":"string","title":"Domain","description":"DD1-DD10."},"category":{"type":"string","title":"Category","description":"The requirement's place in the source inventory."},"reason":{"type":"string","title":"Reason","description":"Why nothing open supplies this."},"observed_by":{"type":"string","title":"Observed By"},"observed":{"type":"string","title":"Observed"},"review_after":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Review After","description":"When somebody should re-check whether this is still true."},"stale":{"type":"boolean","title":"Stale","description":"The review date has passed. Surfaced rather than acted on: an out-of-date 'nothing supplies this' misleads, and hiding the entry would lose both the finding and the fact that it was made.","default":false},"needed_by":{"items":{"type":"string"},"type":"array","title":"Needed By","description":"Analysis classes that require this, from the analysis-type scheme."},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind","description":"Whether the requirement is primary data or a model output."}},"additionalProperties":false,"type":"object","required":["id","title","domain","category","reason","observed_by","observed"],"title":"DataGapModel","description":"A data requirement with no known open supplier (#56).\n\nShaped so it cannot be mistaken for a dataset: no licence, no access path,\nno quality grade, no completeness level. What it has instead is a reason,\nan observer and a date, because a claim about the whole open landscape is\nonly worth anything if a reader can see who made it and when."},"DatasetDetail":{"properties":{"id":{"type":"string","title":"Id"},"iri":{"type":"string","title":"Iri"},"record_type":{"type":"string","title":"Record Type","default":"dataset"},"title":{"type":"string","title":"Title"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"publisher":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Publisher"},"data_domains":{"items":{"$ref":"#/components/schemas/ConceptRef"},"type":"array","title":"Data Domains"},"provenance_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provenance Class"},"license_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Id"},"license_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Label"},"share_alike":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Share Alike"},"license_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Url"},"creators":{"items":{"type":"string"},"type":"array","title":"Creators"},"formats":{"items":{"type":"string"},"type":"array","title":"Formats"},"bulk_download":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bulk Download"},"has_usage_evidence":{"type":"boolean","title":"Has Usage Evidence","default":false},"usage_evidence_count":{"type":"integer","title":"Usage Evidence Count","default":0},"completeness_level":{"type":"integer","title":"Completeness Level","default":1},"reference_only":{"type":"boolean","title":"Reference Only","default":false},"anonymous_access":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Anonymous Access"},"quality":{"items":{"$ref":"#/components/schemas/QualityFacet"},"type":"array","title":"Quality"},"spatial":{"anyOf":[{"$ref":"#/components/schemas/SpatialCoverage"},{"type":"null"}]},"temporal":{"anyOf":[{"$ref":"#/components/schemas/TemporalCoverage"},{"type":"null"}]},"distribution_count":{"type":"integer","title":"Distribution Count","default":0},"worst_link_health":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Worst Link Health"},"modified":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Modified"},"fidelity_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fidelity Class"},"question_classes":{"items":{"$ref":"#/components/schemas/QuestionClassRef"},"type":"array","title":"Question Classes"},"network_element_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Network Element Count"},"redacted":{"type":"boolean","title":"Redacted","default":false},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"keywords":{"items":{"type":"string"},"type":"array","title":"Keywords"},"persistent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Persistent Id"},"doi":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doi"},"supported_analysis":{"items":{"$ref":"#/components/schemas/ConceptRef"},"type":"array","title":"Supported Analysis"},"excluded_analysis":{"items":{"$ref":"#/components/schemas/ConceptRef"},"type":"array","title":"Excluded Analysis"},"exclusion_rationale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exclusion Rationale"},"output_of_analysis":{"items":{"$ref":"#/components/schemas/ConceptRef"},"type":"array","title":"Output Of Analysis"},"derived_from":{"items":{"type":"string"},"type":"array","title":"Derived From"},"assumption_depth":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Assumption Depth","description":"Layers of assumption between this dataset and an observation, over the recorded og:derivedFrom chain. **Null is not zero**: it means the chain is not established, and a modelled product with no lineage recorded must not read as one hop from measurement."},"pointer_rationale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pointer Rationale"},"caveats":{"items":{"type":"string"},"type":"array","title":"Caveats"},"upstream_count":{"type":"integer","title":"Upstream Count","default":0},"supersedes":{"items":{"type":"string"},"type":"array","title":"Supersedes"},"superseded_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Superseded By"},"distributions":{"items":{"$ref":"#/components/schemas/DistributionSummary"},"type":"array","title":"Distributions"},"documentation_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Documentation Status"},"harvest_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Harvest Source"},"review_state":{"type":"string","title":"Review State","default":"confirmed"},"visibility":{"type":"string","enum":["public","restricted-metadata","allowlisted-existence"],"title":"Visibility","default":"public"},"has_topology":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Topology"},"has_impedance":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Impedance"},"voltage_classes":{"items":{"type":"string"},"type":"array","title":"Voltage Classes"},"field_count":{"type":"integer","title":"Field Count","default":0},"usage_evidence":{"items":{"$ref":"#/components/schemas/UsageEvidenceRef"},"type":"array","title":"Usage Evidence"},"last_computed_at":{"additionalProperties":{"type":"string","format":"date-time"},"type":"object","title":"Last Computed At"},"issued":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Issued"}},"additionalProperties":false,"type":"object","required":["id","iri","title"],"title":"DatasetDetail"},"DatasetSummary":{"properties":{"id":{"type":"string","title":"Id"},"iri":{"type":"string","title":"Iri"},"record_type":{"type":"string","title":"Record Type","default":"dataset"},"title":{"type":"string","title":"Title"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"publisher":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Publisher"},"data_domains":{"items":{"$ref":"#/components/schemas/ConceptRef"},"type":"array","title":"Data Domains"},"provenance_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provenance Class"},"license_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Id"},"license_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Label"},"share_alike":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Share Alike"},"license_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Url"},"creators":{"items":{"type":"string"},"type":"array","title":"Creators"},"formats":{"items":{"type":"string"},"type":"array","title":"Formats"},"bulk_download":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bulk Download"},"has_usage_evidence":{"type":"boolean","title":"Has Usage Evidence","default":false},"usage_evidence_count":{"type":"integer","title":"Usage Evidence Count","default":0},"completeness_level":{"type":"integer","title":"Completeness Level","default":1},"reference_only":{"type":"boolean","title":"Reference Only","default":false},"anonymous_access":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Anonymous Access"},"quality":{"items":{"$ref":"#/components/schemas/QualityFacet"},"type":"array","title":"Quality"},"spatial":{"anyOf":[{"$ref":"#/components/schemas/SpatialCoverage"},{"type":"null"}]},"temporal":{"anyOf":[{"$ref":"#/components/schemas/TemporalCoverage"},{"type":"null"}]},"distribution_count":{"type":"integer","title":"Distribution Count","default":0},"worst_link_health":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Worst Link Health"},"modified":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Modified"},"fidelity_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fidelity Class"},"question_classes":{"items":{"$ref":"#/components/schemas/QuestionClassRef"},"type":"array","title":"Question Classes"},"network_element_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Network Element Count"},"redacted":{"type":"boolean","title":"Redacted","default":false}},"additionalProperties":false,"type":"object","required":["id","iri","title"],"title":"DatasetSummary","description":"A list-view row. What PRD §F3 says the list must show, and no more."},"DistributionDetail":{"properties":{"id":{"type":"string","title":"Id"},"access_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Access Url"},"download_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Download Url"},"media_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Media Type"},"format_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format Label"},"byte_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Byte Size"},"checksum":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checksum"},"access_restriction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Access Restriction"},"anonymous_access":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Anonymous Access"},"credential_requirement":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credential Requirement"},"requester_pays":{"type":"boolean","title":"Requester Pays","default":false},"bulk_download":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bulk Download"},"supports_range_requests":{"type":"boolean","title":"Supports Range Requests","default":false},"cors_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cors Enabled"},"chunk_index_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chunk Index Method"},"subsetting_protocol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subsetting Protocol"},"hosted_by_opengrid":{"type":"boolean","title":"Hosted By Opengrid","default":false},"hosting_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hosting Reason"},"link_health":{"anyOf":[{"$ref":"#/components/schemas/LinkHealth"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["id"],"title":"DistributionDetail","description":"One access path, with everything needed to decide how to read it.\n\nBuilt from the record rather than from the search index. The index carries\nonly enough of a distribution to filter and render a list row — no access\nURLs, because a search response should not haul every URL in the catalog\nto a client that wanted ten titles. This is the shape for the caller who\nhas picked a dataset and now wants to fetch it."},"DistributionSummary":{"properties":{"id":{"type":"string","title":"Id"},"media_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Media Type"},"format_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format Label"},"byte_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Byte Size"},"access_restriction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Access Restriction"},"anonymous_access":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Anonymous Access"},"bulk_download":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bulk Download"},"supports_range_requests":{"type":"boolean","title":"Supports Range Requests","default":false},"subsetting_protocol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subsetting Protocol"},"link_health":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Link Health"}},"type":"object","required":["id"],"title":"DistributionSummary","description":"Enough of a distribution to filter and to render a list row."},"DomainResponse":{"properties":{"id":{"type":"string","title":"Id"},"iri":{"type":"string","title":"Iri","description":"The concept IRI, which is what the `data_domain` filter takes. Returned rather than left for a client to build from the id: a client that synthesises an IRI has hardcoded a namespace, and it will be wrong the first time one changes.","default":""},"notation":{"type":"string","title":"Notation"},"label":{"type":"string","title":"Label"},"definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Definition"},"structural_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Structural Note","description":"What is genuinely unavailable in this domain and why. A product feature, not a disclaimer: a catalog that tells you what does not exist is more useful than one that silently returns nothing (PRD §5)."},"v1_ingestion_scope":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"V1 Ingestion Scope"},"dataset_count":{"type":"integer","title":"Dataset Count","default":0},"alt_labels":{"items":{"type":"string"},"type":"array","title":"Alt Labels"}},"additionalProperties":false,"type":"object","required":["id","notation","label"],"title":"DomainResponse"},"FacetBucket":{"properties":{"value":{"title":"Value"},"count":{"type":"integer","title":"Count"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},"additionalProperties":false,"type":"object","required":["value","count"],"title":"FacetBucket"},"FieldDetail":{"properties":{"id":{"type":"string","title":"Id"},"local_name":{"type":"string","title":"Local Name"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Definition"},"data_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Type"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"unit_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit Label"},"concept":{"anyOf":[{"$ref":"#/components/schemas/ConceptRef"},{"type":"null"}]},"concept_inferred":{"type":"boolean","title":"Concept Inferred","default":false},"inference_basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inference Basis"},"concept_gap_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Concept Gap Reason","description":"Why no concept fits. Rule X4: a field with no confident mapping carries an explicit marker, never a silent omission."},"value_basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value Basis"},"field_sources":{"items":{"type":"string"},"type":"array","title":"Field Sources"},"derived_from":{"items":{"type":"string"},"type":"array","title":"Derived From"},"required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Required"},"completeness_caveats":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completeness Caveats"}},"additionalProperties":false,"type":"object","required":["id","local_name"],"title":"FieldDetail"},"GapSearchResponse":{"properties":{"total":{"type":"integer","title":"Total"},"gaps":{"items":{"$ref":"#/components/schemas/DataGapModel"},"type":"array","title":"Gaps"}},"additionalProperties":false,"type":"object","required":["total"],"title":"GapSearchResponse","description":"Counted separately from datasets, and named so.\n\n`total` here is a count of *absences*. A caller adding it to a dataset\ncount would be counting things that do not exist alongside things that do."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthResponse":{"properties":{"status":{"type":"string","enum":["ok","degraded","unhealthy"],"title":"Status"},"version":{"type":"string","title":"Version"},"graph_backend":{"type":"string","title":"Graph Backend"},"search_backend":{"type":"string","title":"Search Backend"},"catalog_records":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Catalog Records"},"projector_lag_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Projector Lag Seconds"},"projector_healthy":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Projector Healthy"},"checks":{"additionalProperties":{"type":"string"},"type":"object","title":"Checks"}},"additionalProperties":false,"type":"object","required":["status","version","graph_backend","search_backend"],"title":"HealthResponse"},"IssuedTokenResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix","description":"The first characters, so you know which one to revoke."},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"token":{"type":"string","title":"Token","description":"Shown once. Only a hash is stored."},"warning":{"type":"string","title":"Warning"}},"additionalProperties":false,"type":"object","required":["id","name","prefix","created_at","token","warning"],"title":"IssuedTokenResponse"},"LinkHealth":{"properties":{"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"last_probed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Probed At"},"consecutive_failures":{"type":"integer","title":"Consecutive Failures","default":0},"probe_cadence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Probe Cadence"},"redirect_target":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Target"}},"additionalProperties":false,"type":"object","title":"LinkHealth","description":"What the prober last saw at this URL.\n\nReported even when it is bad. A dead link a user can see is a reportable\nfact; a dead link silently removed is a dataset that appears to have no\naccess path at all."},"LinkedDataset":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"relation":{"type":"string","enum":["complementary","substitute","supersedes","superseded-by","derived-from","related"],"title":"Relation"},"strength":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Strength","description":"Five-point scale. Not a quality signal."},"descriptor":{"type":"string","title":"Descriptor"},"reasons":{"items":{"type":"string"},"type":"array","title":"Reasons"},"joinable_keys":{"items":{"type":"string"},"type":"array","title":"Joinable Keys"},"shared_workflow_tags":{"items":{"type":"string"},"type":"array","title":"Shared Workflow Tags"},"correlation_warning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Correlation Warning"},"shared_origin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Shared Origin"},"strength_reduced_by_correlation":{"type":"boolean","title":"Strength Reduced By Correlation","default":false}},"additionalProperties":false,"type":"object","required":["dataset_id","relation","strength","descriptor"],"title":"LinkedDataset","description":"One suggested dataset, with the reason it is suggested.\n\nPRD §F6: *every surfaced pairing carries at least one concrete\nhuman-readable reason. A bare numeric score is not sufficient and should\nfail review.* So ``descriptor`` and ``reasons`` are not decoration around\nthe number — they are the payload, and ``strength`` is the ordering."},"LinksResponse":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"links":{"items":{"$ref":"#/components/schemas/LinkedDataset"},"type":"array","title":"Links"},"unavailable_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unavailable Reason"}},"additionalProperties":false,"type":"object","required":["dataset_id"],"title":"LinksResponse"},"MeResponse":{"properties":{"authenticated":{"type":"boolean","title":"Authenticated"},"principal_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Principal Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"role":{"type":"string","title":"Role","default":"anonymous"},"is_agent":{"type":"boolean","title":"Is Agent","default":false},"is_steward":{"type":"boolean","title":"Is Steward","default":false},"custodian_of":{"items":{"type":"string"},"type":"array","title":"Custodian Of"}},"additionalProperties":false,"type":"object","required":["authenticated"],"title":"MeResponse","description":"The caller, as the API sees them.\n\nAnswered for an anonymous caller too: a client asking \"who am I\" wants to\nknow, and \"nobody\" is an answer."},"ProviderList":{"properties":{"providers":{"items":{"type":"string"},"type":"array","title":"Providers"},"native_credentials":{"type":"boolean","title":"Native Credentials","default":false}},"additionalProperties":false,"type":"object","title":"ProviderList"},"QualityFacet":{"properties":{"facet":{"type":"string","enum":["provenance","documentation","currency"],"title":"Facet"},"grade":{"anyOf":[{"type":"string","enum":["A","B","C","D"]},{"type":"null"}],"title":"Grade"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"rationale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rationale","description":"Why this grade. Every grade carries a concrete human-readable reason; a bare letter fails PRD principle 6."},"assessed":{"type":"boolean","title":"Assessed","description":"False for a record below completeness level 2. PRD §F5: such a record shows 'not yet assessed', never grade D — absence of assessment is not poor quality, and conflating them would defame every harvested record.","default":true},"stated_cadence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stated Cadence","description":"Currency only. Displayed alongside the grade so a correctly-scheduled annual dataset does not read as stale next to an hourly one (PRD §F5)."},"computed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Computed At"}},"additionalProperties":false,"type":"object","required":["facet"],"title":"QualityFacet","description":"One of exactly three facets. Never combined (ADR-0007)."},"QualityResponse":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"facets":{"items":{"$ref":"#/components/schemas/QualityFacet"},"type":"array","title":"Facets"},"not_yet_assessed_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Not Yet Assessed Reason"}},"additionalProperties":false,"type":"object","required":["dataset_id","facets"],"title":"QualityResponse"},"QuestionClassRef":{"properties":{"question_class":{"type":"string","title":"Question Class"},"robustness":{"type":"string","enum":["robust","fragile","unknown"],"title":"Robustness"},"basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Basis"}},"type":"object","required":["question_class","robustness"],"title":"QuestionClassRef","description":"One row of a reference model's robust / fragile / unknown partition.\n\nCarried into the index rather than left on the record because it is what a\nreader filters on — \"which networks are rated for this question\" is the\nquestion, and a fidelity class alone cannot answer it.\n\n`basis` is optional here and required by the shapes for \"robust\" only.\nAdmitting a limit costs a reader nothing; claiming one does."},"ReportReceipt":{"properties":{"id":{"type":"string","title":"Id"},"received_at":{"type":"string","format":"date-time","title":"Received At"},"dataset_id":{"type":"string","title":"Dataset Id"},"open_reports_on_target":{"type":"integer","title":"Open Reports On Target","default":1},"message":{"type":"string","title":"Message","default":"Thank you. This has been routed to the curation queue."}},"additionalProperties":false,"type":"object","required":["id","received_at","dataset_id"],"title":"ReportReceipt"},"ReportRequest":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"issue_type":{"type":"string","enum":["incorrect-metadata","broken-link","license-question","wrong-classification","duplicate-record","other"],"title":"Issue Type"},"target_kind":{"type":"string","enum":["dataset","field","distribution"],"title":"Target Kind","default":"dataset"},"captcha_token":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Captcha Token","description":"A human-verification token from the intake form's challenge widget. Optional: deployments that have not configured a challenge ignore it, and the field is absent from the form there."},"target_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Id","description":"The exact thing flagged, captured by the UI rather than typed."},"comment":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Comment"},"reporter_contact":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"title":"Reporter Contact"}},"additionalProperties":false,"type":"object","required":["dataset_id","issue_type"],"title":"ReportRequest","description":"Report an issue against a record, a field or a distribution (PRD §F3)."},"ReviewConfirm":{"properties":{"confirmed_fields":{"items":{"type":"string"},"type":"array","title":"Confirmed Fields","description":"Field paths this review checked. Unioned with what was confirmed before, never replacing it: a second review must not un-confirm the first review's work."},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"additionalProperties":false,"type":"object","title":"ReviewConfirm"},"ReviewItem":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"state":{"type":"string","title":"State"},"source_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Id"},"data_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Domain"},"completeness_level":{"type":"integer","title":"Completeness Level","default":1},"inbound_link_count":{"type":"integer","title":"Inbound Link Count","description":"Why this record is where it is in the queue. Ordering is by leverage: a record twelve others cite is worth reviewing before one nothing points at (PRD §7.6).","default":0},"validation_conforms":{"type":"boolean","title":"Validation Conforms","default":false},"violations":{"items":{},"type":"array","title":"Violations"},"confirmed_fields":{"items":{"type":"string"},"type":"array","title":"Confirmed Fields"},"conflict_detail":{"items":{},"type":"array","title":"Conflict Detail","description":"Set when a re-harvest found the source changing a value under a field a steward had already confirmed. The record is flagged for re-review rather than silently overwritten (PRD §7.6)."},"steward_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Steward Notes"},"reviewed_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reviewed By"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Reviewed At"}},"additionalProperties":false,"type":"object","required":["dataset_id","state"],"title":"ReviewItem","description":"One record awaiting a steward.\n\nCarries the violations rather than a boolean, because \"does not conform\" is\nnot something a steward can act on and \"og:license must be an absolute IRI\"\nis."},"ReviewQueueResponse":{"properties":{"state":{"type":"string","title":"State"},"items":{"items":{"$ref":"#/components/schemas/ReviewItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total","default":0}},"additionalProperties":false,"type":"object","required":["state"],"title":"ReviewQueueResponse"},"SchemaResponse":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"completeness_level":{"type":"integer","title":"Completeness Level"},"fields":{"items":{"$ref":"#/components/schemas/FieldDetail"},"type":"array","title":"Fields"},"total":{"type":"integer","title":"Total","default":0},"returned":{"type":"integer","title":"Returned","default":0},"offset":{"type":"integer","title":"Offset","default":0},"unavailable_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unavailable Reason"}},"additionalProperties":false,"type":"object","required":["dataset_id","completeness_level"],"title":"SchemaResponse"},"SearchResponseModel":{"properties":{"total":{"type":"integer","title":"Total","description":"Entitlement-scoped. A record the caller may not see contributes to no count, which is what stops existence leaking through pagination (ADR-0006)."},"offset":{"type":"integer","title":"Offset"},"limit":{"type":"integer","title":"Limit"},"results":{"items":{"$ref":"#/components/schemas/DatasetSummary"},"type":"array","title":"Results"},"facets":{"additionalProperties":{"items":{"$ref":"#/components/schemas/FacetBucket"},"type":"array"},"type":"object","title":"Facets"},"took_ms":{"type":"number","title":"Took Ms","default":0.0}},"additionalProperties":false,"type":"object","required":["total","offset","limit","results"],"title":"SearchResponseModel"},"SpatialCoverage":{"properties":{"bbox":{"anyOf":[{"items":{"type":"number"},"type":"array"},{"type":"null"}],"title":"Bbox"},"place_labels":{"items":{"type":"string"},"type":"array","title":"Place Labels"},"place_iris":{"items":{"type":"string"},"type":"array","title":"Place Iris"},"native_crs":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Native Crs"},"geometry_types":{"items":{"type":"string"},"type":"array","title":"Geometry Types"},"granularity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Granularity"},"resolution_meters":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Resolution Meters"},"feature_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Feature Count"}},"type":"object","title":"SpatialCoverage"},"SubmissionReceipt":{"properties":{"id":{"type":"string","title":"Id"},"received_at":{"type":"string","format":"date-time","title":"Received At"},"message":{"type":"string","title":"Message","default":"Received. A steward will review it. There is no status to check back on: if it is catalogued you will find it in search."}},"additionalProperties":false,"type":"object","required":["id","received_at"],"title":"SubmissionReceipt"},"SubmissionRequest":{"properties":{"title":{"type":"string","maxLength":500,"minLength":3,"title":"Title"},"description":{"type":"string","maxLength":5000,"minLength":10,"title":"Description"},"access_urls":{"items":{"type":"string"},"type":"array","maxItems":10,"minItems":1,"title":"Access Urls"},"license_text":{"type":"string","maxLength":300,"minLength":2,"title":"License Text"},"originator":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Originator"},"data_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Domain"},"submitter_contact":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"title":"Submitter Contact"},"format_hint":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Format Hint"},"approximate_size":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Approximate Size"},"captcha_token":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Captcha Token","description":"A human-verification token from the intake form's challenge widget. Optional: deployments that have not configured a challenge ignore it, and the field is absent from the form there."},"update_cadence":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Update Cadence"},"documentation_urls":{"items":{"type":"string"},"type":"array","maxItems":10,"title":"Documentation Urls"}},"additionalProperties":false,"type":"object","required":["title","description","access_urls","license_text"],"title":"SubmissionRequest","description":"The intake form (PRD §F3). Fire-and-forget: receipt is confirmed and no\nstatus is tracked back to the submitter."},"TemporalCoverage":{"properties":{"start":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start"},"end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End"},"update_cadence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Update Cadence"},"time_resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time Resolution"}},"type":"object","title":"TemporalCoverage"},"TokenRequest":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"So you can tell them apart."},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"expires_in_days":{"anyOf":[{"type":"integer","maximum":730.0,"minimum":1.0},{"type":"null"}],"title":"Expires In Days"}},"additionalProperties":false,"type":"object","required":["name"],"title":"TokenRequest"},"TokenSummary":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix","description":"The first characters, so you know which one to revoke."},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"}},"additionalProperties":false,"type":"object","required":["id","name","prefix","created_at"],"title":"TokenSummary","description":"A token as it can safely be shown: everything but the token."},"UsageEvidenceRef":{"properties":{"title":{"type":"string","title":"Title"},"url":{"type":"string","title":"Url"},"kind":{"type":"string","title":"Kind"},"author":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author"},"asserted_by":{"type":"string","title":"Asserted By"}},"type":"object","required":["title","url","kind","asserted_by"],"title":"UsageEvidenceRef","description":"A study, tutorial or tool that used this dataset.\n\n`asserted_by` is not decoration. A data provider's self-report through the\nAWS registry, a citation index, and a steward's reading are three different\nstrengths of claim, and a reader who cannot tell them apart is being asked\nto trust the weakest at the strength of the strongest. The UI renders it.\n\n`url` is required all the way down (see `og:UsageEvidenceShape`): a citation\na reader cannot follow is an assertion, and this is the one field where an\nunverifiable one does real damage — it gets carried into somebody's\nbibliography and acquires a second life there."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"datasets","description":"Search and read catalog records."},{"name":"concepts","description":"The SKOS vocabulary and the ten data domains."},{"name":"intake","description":"Submit a dataset, or report a problem with one."},{"name":"auth","description":"Signing in, and the tokens that stand in for it."},{"name":"allowlists","description":"Who may see a restricted dataset. Managed by its custodian; OpenGrid stores and enforces the list and never arbitrates its contents."},{"name":"review","description":"The steward queue. Highest-leverage records first: most inbound links, then most complete."},{"name":"service","description":"Health and readiness."}]}