OGC API - Features

Overview

OGC API - Features is an Open Geospatial Consortium (OGC) standard that provides a modern, RESTful API for accessing vector geospatial features. It is the successor to Web Feature Service (WFS), designed with web developer experience in mind using JSON, OpenAPI, and REST principles.

Key Features

FeatureDescription
RESTfulStandard HTTP methods and URLs
JSON NativeGeoJSON as default output
OpenAPISelf-documenting API specification
PaginationBuilt-in result paging
FilteringCQL2 query language
CORS FriendlyWorks in browsers

Comparison with WFS

AspectOGC API - FeaturesWFS
ProtocolRESTSOAP/XML-RPC
OutputGeoJSONGML (XML)
DocumentationOpenAPIGetCapabilities
QueriesCQL2, bboxFilter Encoding (XML)
Developer UXModernLegacy

Endpoints

EndpointDescription
/Landing page
/conformanceSupported conformance classes
/collectionsList of available collections
/collections/{id}Collection metadata
/collections/{id}/itemsFeatures in collection
/collections/{id}/items/{featureId}Single feature

Query Parameters

ParameterDescriptionExample
limitMax features to return?limit=100
offsetStarting position?offset=100
bboxBounding box filter?bbox=-122.5,37.7,-122.3,37.9
datetimeTemporal filter?datetime=2024-01-01/2024-12-31
filterCQL2 filter expression?filter=area>10000
filter-langFilter language?filter-lang=cql2-text

Example Requests

Get Collections

GET /collections HTTP/1.1
Accept: application/json

Get Features with Bbox

GET /collections/parcels/items?bbox=-122.5,37.7,-122.3,37.9&limit=100 HTTP/1.1
Accept: application/geo+json

Get Single Feature

GET /collections/parcels/items/12345 HTTP/1.1
Accept: application/geo+json

Filter with CQL2

GET /collections/parcels/items?filter=area>10000 AND owner LIKE 'Smith%' HTTP/1.1
Accept: application/geo+json

Server Implementations

ServerLanguageLinks
pygeoapiPythonGitHub
pg_featureservGoGitHub
tipgPythonGitHub
ldproxyJavaGitHub
GeoServerJavaWebsite

R Client

library(httr2)
library(sf)
 
# query ogc api features
get_features <- function(base_url, collection, bbox = NULL, limit = 100) {
  url <- paste0(base_url, "/collections/", collection, "/items")
  
  req <- httr2::request(url) |>
    httr2::req_url_query(limit = limit, f = "json")
  
  if (!is.null(bbox)) {
    req <- req |>
      httr2::req_url_query(bbox = paste(bbox, collapse = ","))
  }
  
  resp <- req |> httr2::req_perform()
  geojson <- httr2::resp_body_json(resp)
  
 sf::st_read(jsonlite::toJSON(geojson, auto_unbox = TRUE), quiet = TRUE)
}

Appendix

Created: 2024-12-23 | Modified: 2024-12-23

See Also


(c) No Clocks, LLC | 2024