Admin Endpoints
Administration endpoints live under /api/admin/ to keep the OGC namespace clean.
Workspaces
List workspaces
GET /api/admin/workspacesReturns all workspaces. A default workspace is always present.
Create a workspace
POST /api/admin/workspaces{ "name": "transport", "description": "Transport datasets" }Returns 409 Conflict if a workspace with the same name already exists.
Get a workspace
GET /api/admin/workspaces/{id}Update a workspace
PUT /api/admin/workspaces/{id}{ "name": "transport", "description": "Updated description" }Delete a workspace
DELETE /api/admin/workspaces/{id}Deleting a workspace cascades to all its collections.
Collections
List collections
GET /api/admin/collectionsSupports filtering by workspace:
GET /api/admin/collections?workspace_id={uuid}Get a collection
GET /api/admin/collections/{id}Returns full collection metadata including bounding box, feature count, geometry type, and SRID.
Update a collection
PUT /api/admin/collections/{id}All fields are optional — only provided fields are updated.
{
"workspace_id": "uuid",
"name": "new_name",
"description": "Updated description",
"attribution": "© OpenStreetMap contributors",
"datetime_column": "date_created",
"exposed_fields": [{ "source": "name", "alias": "city" }, { "source": "population" }],
"style": { "type": "single", "fill_color": "#1B4F72", "fill_opacity": 0.3 },
"default_center_lon": 2.35,
"default_center_lat": 48.85,
"default_zoom": 12.5
}| Field | Type | Description |
|---|---|---|
workspace_id | string | Move the collection to a different workspace |
name | string | Rename the collection |
description | string | null | Collection description (set to null to clear) |
attribution | string | null | Data attribution text |
datetime_column | string | null | Column to use for OGC ?datetime= temporal filtering |
exposed_fields | array | null | Columns to expose in the API (see Exposed Fields) |
style | object | null | Render style configuration (see Collection Style) |
default_center_lon | number | null | Default map center longitude in WGS84 (-180–180) |
default_center_lat | number | null | Default map center latitude in WGS84 (-90–90) |
default_zoom | number | null | Default map zoom (0–24, decimals supported) |
When all three default_center_lon, default_center_lat, default_zoom are set, the admin UI Map and Style tabs open directly on that view. Set them to null to fall back to auto-fit on the collection bounding box.
Export collection data
GET /api/admin/collections/{id}/exportDownloads the full collection. The response includes a Content-Disposition header for browser download. If exposed_fields is configured, only those columns are included in the export.
Query parameters:
| Param | Type | Description |
|---|---|---|
format | string | geojson (default) or csv |
filter | string | CQL2 text filter (same syntax as /items?filter=) |
bbox | string | Bounding box minLon,minLat,maxLon,maxLat in WGS84 |
limit | number | Maximum number of features to return |
format=geojson returns an application/geo+json FeatureCollection. format=csv returns text/csv;charset=utf-8 with one header row (id, the exposed property names, and geom_wkt) followed by one row per feature; geom_wkt holds the geometry as WKT in EPSG:4326.
Delete a collection
DELETE /api/admin/collections/{id}Deleting a collection:
- Drops the associated PostGIS data table
- Cascades to import history records
Collection schema
GET /api/admin/collections/{id}/schemaReturns column names, types, and basic statistics (distinct values, nulls) for the collection's data table.
Collection import history
GET /api/admin/collections/{id}/historyReturns the import history for a specific collection, with progress and timing details.
Import
Preview a file
POST /api/admin/import/previewMultipart form data with a single file field. Analyzes the file and returns metadata, sample data, and sample GeoJSON without importing anything.
Response:
{
"format": "geojson",
"feature_count": 1234,
"geometry_type": "MultiPolygon",
"srid": null,
"fields": [
{ "name": "name", "type": "TEXT" },
{ "name": "population", "type": "INTEGER" }
],
"csv_info": null,
"sample_rows": [{ "name": "Paris", "population": 2161000 }],
"sample_geojson": { "type": "FeatureCollection", "features": ["...first 100 features..."] },
"bbox": [2.22, 48.81, 2.47, 48.9]
}For CSV files, csv_info includes the detected separator, longitude column, and latitude column. For Shapefiles, srid is populated from the .prj file. The sample_geojson contains up to 100 features for map display.
Upload and import a file
POST /api/admin/importMultipart form data with the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | GeoJSON (.geojson, .json, .geojson.gz, .gz), CSV (.csv), or Shapefile (.zip) |
workspace_id | string | Yes | Target workspace UUID |
collection_name | string | Yes | Name for the collection |
srid | number | No | Source SRID (default: 4326) |
separator | string | No | CSV only — column separator (auto-detected if omitted) |
longitude | string | No | CSV only — longitude column name (auto-detected if omitted) |
latitude | string | No | CSV only — latitude column name (auto-detected if omitted) |
Response (202 Accepted):
{
"import_id": "abc123-...",
"status": "pending",
"message": "Import job queued"
}Jobs
List jobs
GET /api/admin/jobs| Parameter | Description |
|---|---|
status | Filter by status: pending, running, completed, failed |
collection_id | Filter by collection UUID |
limit | Number of results (default: 20) |
offset | Pagination offset |
Returns jobs ordered by created_at descending.
Get job details
GET /api/admin/jobs/{id}Returns full job details including progress, logs, and timing:
{
"id": "abc123-...",
"source_file": "regions.geojson",
"collection_name": "regions",
"status": "running",
"progress": 45,
"total_features": 1000,
"imported_features": 450,
"logs": [
{
"ts": "2026-03-14T10:00:01Z",
"level": "info",
"message": "Starting import of regions.geojson"
},
{ "ts": "2026-03-14T10:00:02Z", "level": "info", "message": "Parsed 1000 features" },
{ "ts": "2026-03-14T10:00:03Z", "level": "info", "message": "Table data_regions ready" },
{ "ts": "2026-03-14T10:00:05Z", "level": "info", "message": "450/1000 features imported" }
],
"error": null,
"duration_ms": null,
"created_at": "2026-03-14T10:00:00Z",
"started_at": "2026-03-14T10:00:01Z",
"completed_at": null
}Job statuses
| Status | Description |
|---|---|
pending | Job is queued, waiting for a worker |
running | Worker is processing the import |
completed | Import finished successfully |
failed | Import failed (see error field and logs) |
Failed jobs are automatically retried up to 3 times by pg-boss, with a 30-second delay between attempts.
Exposed Fields
By default, all columns from the data table are exposed in the OGC API (features, queryables, vector tiles, and export). You can restrict which columns are visible by configuring exposed_fields on a collection.
Behavior
exposed_fields value | Effect |
|---|---|
null (default) | All columns are exposed |
[] (empty array) | Only geometry and ID are exposed |
[{source, alias?}, ...] | Only listed columns are exposed |
Aliasing
Each exposed field can have an optional alias. When set, the alias replaces the original column name in all API responses:
{
"exposed_fields": [
{ "source": "nom_commune", "alias": "city" },
{ "source": "pop_totale", "alias": "population" }
]
}With this configuration, API consumers see city and population as property names instead of the raw column names.
Affected endpoints
Exposed fields filtering applies to:
- Features (
/collections/{id}/items) — only configured columns appear inproperties - Single feature (
/collections/{id}/items/{fid}) — same filtering - Queryables (
/collections/{id}/queryables) — only exposed columns are listed as filterable - Vector tiles (
/collections/{id}/tiles/{z}/{x}/{y}.pbf) — MVT properties reflect exposed fields - Export (
/api/admin/collections/{id}/export) — both GeoJSON and CSV outputs respect the configuration
Collection Style
Collections can have a style configuration that defines how features should be rendered. The style is stored as JSONB and supports three classification types.
Style types
Single — one color for all features:
{
"type": "single",
"fill_color": "#1B4F72",
"fill_opacity": 0.3,
"stroke_color": "#1B4F72",
"stroke_width": 1.5
}Categorized — unique values mapped to colors:
{
"type": "categorized",
"field": "category",
"categories": [
{ "value": "capital", "color": "#e41a1c", "label": "Capital" },
{ "value": "major", "color": "#377eb8", "label": "Major city" }
],
"default_color": "#cccccc",
"fill_opacity": 0.5
}Graduated — numeric ranges mapped to colors:
{
"type": "graduated",
"field": "population",
"method": "quantile",
"classes": [
{ "min": 0, "max": 100000, "color": "#eff3ff" },
{ "min": 100000, "max": 500000, "color": "#6baed6" },
{ "min": 500000, "max": 2200000, "color": "#08519c" }
],
"default_color": "#cccccc",
"fill_opacity": 0.5
}Save a style via the Update a collection endpoint (PUT /api/admin/collections/{id} with a style field). Set style to null to remove it.
Auto-classify
GET /api/admin/collections/{id}/classifyGenerates classification suggestions from the actual data.
| Parameter | Type | Required | Description |
|---|---|---|---|
field | string | Yes | Column name to classify |
type | string | Yes | categorized or graduated |
classes | number | No | Number of classes for graduated (default: 5) |
For categorized, returns up to 50 distinct values. For graduated, computes quantile breakpoints.
OGC style endpoint
GET /collections/{collectionId}/styleReturns the style configuration for a collection. Returns 204 No Content if no style is configured.
