830 lines
26 KiB
YAML
830 lines
26 KiB
YAML
openapi: 3.1.1
|
|
info:
|
|
title: GIS API
|
|
version: "1.0.0"
|
|
summary: Hierarchical categories and geo datasets with async processing.
|
|
description: |
|
|
HTTP API for hierarchical categories and geo datasets (vector,
|
|
vector_with_kato, raster).
|
|
|
|
Datasets are processed asynchronously after upload, dispatched by `file_type`:
|
|
- `vector` — the attribute table is extracted into `properties`.
|
|
- `raster` — converted to a Cloud-Optimized GeoTIFF; footprint `geometry`
|
|
and `bbox` are derived from the raster extent.
|
|
- `vector_with_kato` — columns are detected for selection; the client then
|
|
submits a KATO/year mapping, unpivoted into observations.
|
|
|
|
Poll `GET /datasets/{id}/status` (optionally long-polling) to follow progress
|
|
through the status lifecycle:
|
|
`pending → processing|parsing → awaiting_mapping → extracting → ready`
|
|
(or `failed`).
|
|
license:
|
|
name: Proprietary
|
|
|
|
servers:
|
|
- url: http://localhost:8080
|
|
description: Local development
|
|
|
|
tags:
|
|
- name: Health
|
|
description: Liveness and readiness probes
|
|
- name: Categories
|
|
description: Hierarchical dataset categories
|
|
- name: Datasets
|
|
description: Geo dataset upload, processing, and retrieval
|
|
|
|
paths:
|
|
/healthz:
|
|
get:
|
|
tags: [Health]
|
|
summary: Liveness probe
|
|
responses:
|
|
"200":
|
|
description: Process is alive
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
|
|
/readyz:
|
|
get:
|
|
tags: [Health]
|
|
summary: Readiness probe
|
|
description: Runs dependency checks (Postgres, S3/MinIO, RabbitMQ).
|
|
responses:
|
|
"200":
|
|
description: All dependencies reachable
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Readiness" }
|
|
"503":
|
|
description: One or more dependencies unavailable
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Readiness" }
|
|
|
|
/categories:
|
|
get:
|
|
tags: [Categories]
|
|
summary: List categories
|
|
parameters:
|
|
- name: parent_id
|
|
in: query
|
|
required: false
|
|
description: Filter to the direct children of this category.
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
"200":
|
|
description: Categories ordered by name
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/Category" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
post:
|
|
tags: [Categories]
|
|
summary: Create a category
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CategoryInput" }
|
|
responses:
|
|
"201":
|
|
description: Created
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Category" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"409": { $ref: "#/components/responses/Conflict" }
|
|
"422": { $ref: "#/components/responses/ValidationError" }
|
|
|
|
/categories/{id}:
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdParam"
|
|
get:
|
|
tags: [Categories]
|
|
summary: Get a category
|
|
responses:
|
|
"200":
|
|
description: The category
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Category" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
put:
|
|
tags: [Categories]
|
|
summary: Update a category
|
|
description: |
|
|
Updates name, description, and parent. The new parent must exist and must
|
|
not create a cycle (a category cannot be its own ancestor).
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CategoryInput" }
|
|
responses:
|
|
"200":
|
|
description: Updated
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Category" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
"409": { $ref: "#/components/responses/Conflict" }
|
|
"422": { $ref: "#/components/responses/ValidationError" }
|
|
delete:
|
|
tags: [Categories]
|
|
summary: Delete a category
|
|
description: Fails with 409 if datasets or child categories still reference it.
|
|
responses:
|
|
"204": { description: Deleted }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
"409": { $ref: "#/components/responses/Conflict" }
|
|
|
|
/datasets:
|
|
get:
|
|
tags: [Datasets]
|
|
summary: List datasets (paginated summaries)
|
|
parameters:
|
|
- $ref: "#/components/parameters/PageParam"
|
|
- $ref: "#/components/parameters/PageSizeParam"
|
|
- name: category_id
|
|
in: query
|
|
required: false
|
|
description: Filter to a category by id.
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
- name: category_code
|
|
in: query
|
|
required: false
|
|
description: >-
|
|
Filter to a category by its code (slug). An unknown code yields an
|
|
empty page.
|
|
schema:
|
|
type: string
|
|
- name: file_type
|
|
in: query
|
|
required: false
|
|
description: Filter by file type.
|
|
schema:
|
|
type: string
|
|
enum: [vector_with_kato, vector, raster]
|
|
- name: automated
|
|
in: query
|
|
required: false
|
|
description: Filter by the automated flag.
|
|
schema:
|
|
type: boolean
|
|
- name: status
|
|
in: query
|
|
required: false
|
|
description: Filter by lifecycle status.
|
|
schema:
|
|
type: string
|
|
enum:
|
|
[pending, parsing, processing, awaiting_mapping, extracting, ready, failed]
|
|
responses:
|
|
"200":
|
|
description: A page of dataset summaries
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/DatasetSummaryPage" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
post:
|
|
tags: [Datasets]
|
|
summary: Upload a dataset
|
|
description: |
|
|
Multipart upload, validated by `file_type`, extension, and a content
|
|
magic-byte check, then processed asynchronously (poll
|
|
`GET /datasets/{id}/status`).
|
|
|
|
Allowed extensions: `vector`/`vector_with_kato` = `.geojson`/`.gpkg`/`.zip`;
|
|
`raster` = `.tif`/`.tiff`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [file, file_type, category_id]
|
|
properties:
|
|
file:
|
|
type: string
|
|
format: binary
|
|
description: The geo file.
|
|
file_type:
|
|
$ref: "#/components/schemas/FileType"
|
|
category_id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
description: Display name; defaults to the filename if omitted.
|
|
description:
|
|
type: string
|
|
unit:
|
|
type: string
|
|
meta:
|
|
type: string
|
|
description: Arbitrary user JSON (sent as a JSON string).
|
|
automated:
|
|
type: boolean
|
|
responses:
|
|
"201":
|
|
description: Dataset created; processing enqueued
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Dataset" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"422": { $ref: "#/components/responses/ValidationError" }
|
|
|
|
/datasets/{id}:
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdParam"
|
|
get:
|
|
tags: [Datasets]
|
|
summary: Get a dataset
|
|
description: Full dataset, including geometry as GeoJSON and bbox for rasters.
|
|
responses:
|
|
"200":
|
|
description: The dataset
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Dataset" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
delete:
|
|
tags: [Datasets]
|
|
summary: Delete a dataset
|
|
description: Removes the row and the stored object(s).
|
|
responses:
|
|
"204": { description: Deleted }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
|
|
/datasets/{id}.geojson:
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdParam"
|
|
get:
|
|
tags: [Datasets]
|
|
summary: Get a dataset as GeoJSON (vector / vector_with_kato)
|
|
description: |
|
|
Assembles a GeoJSON `FeatureCollection` (RFC 7946) from the dataset.
|
|
|
|
A plain `vector` dataset has no KATO mapping or observations, so the
|
|
result is a single Feature wrapping the dataset's own (dissolved)
|
|
geometry. Its extracted attribute table (e.g. a GeoPackage's table data,
|
|
stored in `properties`) is exposed as the Feature's top-level properties:
|
|
a single row becomes the properties object directly, multiple rows are
|
|
kept under a `rows` key. An empty collection is returned when the dataset
|
|
has no geometry.
|
|
|
|
A `vector_with_kato` dataset is built from its observations. When it has
|
|
its own (dissolved) geometry, the observations are taken to describe that
|
|
whole geometry: a single Feature wraps it, and its properties hold only
|
|
the observations, keyed by KATO code at the top level (each KATO mapping
|
|
to its date->value pairs). Otherwise one Feature is emitted per KATO, its
|
|
boundary taken from the `districts` table and the per-year values
|
|
flattened into the Feature's properties keyed by date; KATO codes with
|
|
no matching district are skipped.
|
|
|
|
Only `ready` datasets are served: a dataset still being processed
|
|
returns 409. Other file types (e.g. `raster`) return 422.
|
|
responses:
|
|
"200":
|
|
description: The dataset as a GeoJSON FeatureCollection
|
|
content:
|
|
application/geo+json:
|
|
schema: { $ref: "#/components/schemas/GeoJSONFeatureCollection" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
"409": { $ref: "#/components/responses/Conflict" }
|
|
"422": { $ref: "#/components/responses/ValidationError" }
|
|
|
|
/datasets/{id}.kato.geojson:
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdParam"
|
|
get:
|
|
tags: [Datasets]
|
|
summary: Get a dataset as district-joined GeoJSON (vector_with_kato)
|
|
description: |
|
|
Like `/datasets/{id}.geojson`, but ignores any geometry the dataset
|
|
carries and always joins the `districts` table on KATO code: one Feature
|
|
is emitted per KATO, its boundary taken from the matching district and
|
|
the per-year observation values mapped into the Feature's properties
|
|
keyed by date (alongside `kato` and `name`). KATO codes with no matching
|
|
district are skipped.
|
|
|
|
Only `ready` datasets are served: a dataset still being processed
|
|
returns 409. Other file types return 422.
|
|
responses:
|
|
"200":
|
|
description: The dataset as a district-joined GeoJSON FeatureCollection
|
|
content:
|
|
application/geo+json:
|
|
schema: { $ref: "#/components/schemas/GeoJSONFeatureCollection" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
"409": { $ref: "#/components/responses/Conflict" }
|
|
"422": { $ref: "#/components/responses/ValidationError" }
|
|
|
|
/datasets/{id}/status:
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdParam"
|
|
get:
|
|
tags: [Datasets]
|
|
summary: Get processing status (supports long polling)
|
|
description: |
|
|
Returns the current status immediately. If `current` is supplied, the
|
|
request is held until the status differs from it, or until `wait` seconds
|
|
elapse (then the unchanged status is returned).
|
|
parameters:
|
|
- name: current
|
|
in: query
|
|
required: false
|
|
description: The client's last-known status; enables long polling.
|
|
schema: { $ref: "#/components/schemas/DatasetStatus" }
|
|
- name: wait
|
|
in: query
|
|
required: false
|
|
description: Max seconds to hold the request (default 25, max 60).
|
|
schema:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 60
|
|
default: 25
|
|
responses:
|
|
"200":
|
|
description: The dataset's status
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/DatasetStatusInfo" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
|
|
/datasets/{id}/download:
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdParam"
|
|
get:
|
|
tags: [Datasets]
|
|
summary: Download the original uploaded file
|
|
responses:
|
|
"200":
|
|
description: The file stream
|
|
content:
|
|
application/octet-stream:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
|
|
/datasets/{id}/mapping:
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdParam"
|
|
post:
|
|
tags: [Datasets]
|
|
summary: Set the KATO column and year mapping (vector_with_kato)
|
|
description: |
|
|
Valid only for `vector_with_kato` datasets in `awaiting_mapping` (or
|
|
`ready`, to re-map). The KATO column and every mapped column must be among
|
|
the dataset's detected `attribute_columns`. Moves the dataset to
|
|
`extracting`; observations are produced asynchronously.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/MappingInput" }
|
|
responses:
|
|
"200":
|
|
description: Mapping saved; extraction enqueued
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Dataset" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
"409": { $ref: "#/components/responses/Conflict" }
|
|
"422": { $ref: "#/components/responses/ValidationError" }
|
|
|
|
/datasets/{id}/observations:
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdParam"
|
|
get:
|
|
tags: [Datasets]
|
|
summary: List a dataset's observations (paginated)
|
|
description: Long-format values unpivoted from a vector_with_kato dataset.
|
|
parameters:
|
|
- name: kato_code
|
|
in: query
|
|
required: false
|
|
description: Filter to a single KATO code.
|
|
schema:
|
|
type: string
|
|
- $ref: "#/components/parameters/PageParam"
|
|
- $ref: "#/components/parameters/PageSizeParam"
|
|
responses:
|
|
"200":
|
|
description: A page of observations
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ObservationPage" }
|
|
"400": { $ref: "#/components/responses/BadRequest" }
|
|
"404": { $ref: "#/components/responses/NotFound" }
|
|
|
|
components:
|
|
parameters:
|
|
IdParam:
|
|
name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
PageParam:
|
|
name: page
|
|
in: query
|
|
required: false
|
|
description: 1-based page number.
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
PageSizeParam:
|
|
name: page_size
|
|
in: query
|
|
required: false
|
|
description: Items per page (default 20, max 100).
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 100
|
|
default: 20
|
|
|
|
responses:
|
|
BadRequest:
|
|
description: Malformed request (e.g. invalid UUID or query parameter)
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Error" }
|
|
NotFound:
|
|
description: Resource not found
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Error" }
|
|
Conflict:
|
|
description: Operation conflicts with existing data (e.g. foreign key)
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/Error" }
|
|
ValidationError:
|
|
description: Input failed validation
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- { $ref: "#/components/schemas/Error" }
|
|
- { $ref: "#/components/schemas/ValidationErrors" }
|
|
|
|
schemas:
|
|
Error:
|
|
type: object
|
|
required: [error]
|
|
properties:
|
|
error:
|
|
type: string
|
|
|
|
ValidationErrors:
|
|
type: object
|
|
description: Per-field validation messages.
|
|
properties:
|
|
errors:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
|
|
Readiness:
|
|
type: object
|
|
properties:
|
|
ready:
|
|
type: boolean
|
|
components:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
|
|
FileType:
|
|
type: string
|
|
enum: [vector_with_kato, vector, raster]
|
|
|
|
DatasetStatus:
|
|
type: string
|
|
description: Dataset processing lifecycle status.
|
|
enum: [pending, processing, parsing, awaiting_mapping, extracting, ready, failed]
|
|
|
|
Category:
|
|
type: object
|
|
required: [id, code, name, description, created_at, updated_at]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
parent_id:
|
|
type: [string, "null"]
|
|
format: uuid
|
|
code:
|
|
type: string
|
|
description: Slug (lowercase latin letters, digits, and dashes).
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
CategoryInput:
|
|
type: object
|
|
required: [code, name]
|
|
properties:
|
|
parent_id:
|
|
type: [string, "null"]
|
|
format: uuid
|
|
code:
|
|
type: string
|
|
maxLength: 255
|
|
pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$"
|
|
description: Slug (lowercase latin letters, digits, and dashes).
|
|
name:
|
|
type: string
|
|
maxLength: 255
|
|
description:
|
|
type: string
|
|
maxLength: 2000
|
|
|
|
AttributeColumn:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
samples:
|
|
type: array
|
|
items:
|
|
type: string
|
|
|
|
YearColumn:
|
|
type: object
|
|
required: [column, date]
|
|
properties:
|
|
column:
|
|
type: string
|
|
date:
|
|
type: string
|
|
format: date
|
|
|
|
GeoJSONGeometry:
|
|
type: [object, "null"]
|
|
description: A GeoJSON geometry object (e.g. Point, Polygon).
|
|
properties:
|
|
type:
|
|
type: string
|
|
coordinates: true
|
|
|
|
GeoJSONFeature:
|
|
type: object
|
|
description: A GeoJSON Feature (RFC 7946).
|
|
required: [type, geometry, properties]
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [Feature]
|
|
geometry:
|
|
$ref: "#/components/schemas/GeoJSONGeometry"
|
|
properties:
|
|
type: [object, "null"]
|
|
description: |
|
|
Arbitrary key/value map. For per-KATO features (no dataset geometry)
|
|
this holds `kato`, `name`, and one entry per mapped year keyed by
|
|
date (YYYY-MM-DD). For the single-feature case (dataset has its own
|
|
geometry) it holds only the observations, keyed by KATO code, each
|
|
mapping to its date->value pairs.
|
|
additionalProperties: true
|
|
|
|
GeoJSONFeatureCollection:
|
|
type: object
|
|
description: A GeoJSON FeatureCollection (RFC 7946).
|
|
required: [type, features]
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [FeatureCollection]
|
|
features:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/GeoJSONFeature"
|
|
|
|
DatasetSummary:
|
|
type: object
|
|
required: [id, category_id, name, file_type, size_bytes, status, created_at, updated_at]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
category_id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
description:
|
|
type: [string, "null"]
|
|
unit:
|
|
type: [string, "null"]
|
|
file_type:
|
|
$ref: "#/components/schemas/FileType"
|
|
size_bytes:
|
|
type: integer
|
|
format: int64
|
|
status:
|
|
$ref: "#/components/schemas/DatasetStatus"
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
Dataset:
|
|
type: object
|
|
required:
|
|
[id, category_id, name, filename, storage_key, file_type,
|
|
size_bytes, content_type, automated, status, created_at, updated_at]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
category_id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
description:
|
|
type: [string, "null"]
|
|
unit:
|
|
type: [string, "null"]
|
|
filename:
|
|
type: string
|
|
storage_key:
|
|
type: string
|
|
cog_storage_key:
|
|
type: [string, "null"]
|
|
description: Set for rasters once the Cloud-Optimized GeoTIFF is produced.
|
|
file_type:
|
|
$ref: "#/components/schemas/FileType"
|
|
size_bytes:
|
|
type: integer
|
|
format: int64
|
|
content_type:
|
|
type: string
|
|
properties:
|
|
type: [array, "null"]
|
|
description: Extracted attribute table (plain vector); rows of key/value.
|
|
items:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
meta:
|
|
type: [object, "null"]
|
|
description: Arbitrary user-supplied JSON.
|
|
automated:
|
|
type: boolean
|
|
status:
|
|
$ref: "#/components/schemas/DatasetStatus"
|
|
attribute_columns:
|
|
type: [array, "null"]
|
|
description: Detected columns (vector_with_kato), for mapping.
|
|
items:
|
|
$ref: "#/components/schemas/AttributeColumn"
|
|
kato_column:
|
|
type: [string, "null"]
|
|
year_columns:
|
|
type: [array, "null"]
|
|
items:
|
|
$ref: "#/components/schemas/YearColumn"
|
|
parse_error:
|
|
type: [string, "null"]
|
|
description: Failure reason when status is `failed`.
|
|
geometry:
|
|
$ref: "#/components/schemas/GeoJSONGeometry"
|
|
bbox:
|
|
type: array
|
|
description: "[minX, minY, maxX, maxY]; present only for rasters."
|
|
items:
|
|
type: number
|
|
minItems: 4
|
|
maxItems: 4
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
MappingInput:
|
|
type: object
|
|
required: [kato_column, year_columns]
|
|
properties:
|
|
kato_column:
|
|
type: string
|
|
examples: ["като"]
|
|
year_columns:
|
|
type: array
|
|
minItems: 1
|
|
items:
|
|
$ref: "#/components/schemas/YearColumn"
|
|
examples:
|
|
- kato_column: "като"
|
|
year_columns:
|
|
- { column: F_2023, date: "2023-01-01" }
|
|
- { column: D_2025, date: "2025-01-01" }
|
|
|
|
Observation:
|
|
type: object
|
|
required: [id, dataset_id, kato_code, date]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
dataset_id:
|
|
type: string
|
|
format: uuid
|
|
kato_code:
|
|
type: string
|
|
date:
|
|
type: string
|
|
format: date
|
|
value:
|
|
type: [number, "null"]
|
|
description: Numeric cell value, or null when non-numeric/empty.
|
|
value_text:
|
|
type: [string, "null"]
|
|
description: Non-numeric cell value, or null.
|
|
|
|
DatasetStatusInfo:
|
|
type: object
|
|
required: [id, status]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
status:
|
|
$ref: "#/components/schemas/DatasetStatus"
|
|
parse_error:
|
|
type: [string, "null"]
|
|
|
|
DatasetSummaryPage:
|
|
type: object
|
|
required: [data, page, page_size, total, total_pages]
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/DatasetSummary"
|
|
page:
|
|
type: integer
|
|
page_size:
|
|
type: integer
|
|
total:
|
|
type: integer
|
|
total_pages:
|
|
type: integer
|
|
|
|
ObservationPage:
|
|
type: object
|
|
required: [data, page, page_size, total, total_pages]
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Observation"
|
|
page:
|
|
type: integer
|
|
page_size:
|
|
type: integer
|
|
total:
|
|
type: integer
|
|
total_pages:
|
|
type: integer
|