Open implementation notes

From public geodata to a honey-production estimate.

This is the practical handoff for another software team: which services SiBeela calls, how it calls them, how it turns their responses into parcels, and where each country's coverage stops.

Eduardo Marcos Alejos · Senior Programmer and Data Scientist · BeeLife — BeeLife European Beekeeping Coordination

6 countriesWMS · WFS · GeoJSON · GML · ArcGIS RESTNo hidden country endpoint
01 / PlaceApiary latitude, longitude and radius
02 / QueryCountry parcel service and visual layers
03 / NormalizeCrop, hectares, centre, source and score
04 / EnrichForest, satellite and climate signals
05 / EstimateCountry floral catalogue and honey model

Core distinction. A WMS layer paints an image on the map. A WFS, vector tile or ArcGIS feature request returns records and attributes that the model can actually calculate with. Seeing a cadastral layer does not mean crop data is available for prediction.

Implemented in the repositoryProvider change requiring reviewDocumented alternative, not integrated

Every example URL in this document is a public provider URL or a placeholder such as YOUR_BACKEND. The document contains no production server address, service-account identity, private key, access token, API key or billing identifier. Example coordinates and JSON values are illustrative.

The reusable integration recipe

For Sweden, France, Italy, Belgium and Germany, the browser calls the public feature service through SiBeela's Node endpoint GET /proxy?url=.... The proxy relays the response, caches successful URLs for 10 minutes, retries server errors and rejects private/internal destinations. Spain's preferred vector route is implemented directly in the backend.

1

Build a geographic window. From the apiary centre and radius in kilometres: dLat = radiusKm / 111, dLon = radiusKm / (111 × cos(latitude)). Send the resulting bounding box in the axis order expected by that provider.

2

Request features in pages. Most country adapters use WFS 2.0 GetFeature with typeNames, outputFormat, srsName=EPSG:4326, bbox, count and startIndex. Request another page until it has fewer features than the page size.

3

Make records comparable. Read each polygon's centre, discard centres outside the requested circle, deduplicate on the provider ID, map local crop fields to cropKey/usoCode, record hectares and provenance.

4

Apply the bee model. The country crop catalogue maps recognised uses to floral species; monthly phenology, parcel area, distance and biological limits shape the estimate. Uncertain or forest parcels can be enriched with OSM and Dynamic World.

Proxy pattern
const upstream = new URL('https://data.geopf.fr/wfs');
upstream.search = new URLSearchParams({
  SERVICE: 'WFS', VERSION: '2.0.0', REQUEST: 'GetFeature',
  TYPENAMES: 'RPG.LATEST:parcelles_graphiques',
  outputFormat: 'application/json', SRSNAME: 'EPSG:4326',
  COUNT: '500', startIndex: '0',
  BBOX: '2.30,48.80,2.40,48.90,EPSG:4326'
});
const response = await fetch('/proxy?url=' + encodeURIComponent(upstream));
if (!response.ok) throw new Error(`WFS HTTP ${response.status}`);
const geojson = await response.json();

The country's production adapter is selected by BeeLifeCountries. Both the grid and geometric prediction choices route non-Spanish countries to the same country adapter. Their WFS census is therefore the operative parcel connection for those countries.

CountryActual analytical connectionMap connectionHow specific is the source?
SpainHubCloud GeoJSON vector tiles via Node; Catastro + SIGPAC WMS fallbackSIGPAC WMSParcel and declared product when present
SwedenJordbruksverket block WFSBlock/skifte WMSBlock land-use class; skifte shown, not sampled
FranceIGN RPG WFS + code dictionaryRPG WMSDeclared agricultural parcel and culture code
ItalyEmilia-Romagna land-use WFSNational Catasto WMS; regional WFS overlayRegional land-use category, not a national crop census
BelgiumFlanders WFS + Wallonia legacy 2023 WFSFlanders WMS; Wallonia WFS overlayRegional crop name/code; Wallonia migration required
GermanyLand-specific WFS JSON, WFS GML or ArcGIS RESTFetched GeoJSON overlayCrop parcels in some Länder; reference blocks in others

How to make a request that can be reproduced

The provider's URL is only one part of a working connection. The layer name, CRS, BBOX order, output format, pagination and interpretation of the response are equally important. The examples below show the exact mechanics used by the adapters.

A

Find the layer first

Call ?service=WFS&request=GetCapabilities to discover feature type names, supported formats and CRS. Call ?service=WMS&request=GetCapabilities to discover image-layer names. A layer name can change by year; hard-coded names should be checked before release.

B

Know the coordinate order

GeoJSON geometry uses [longitude, latitude]. A WFS 2.0 EPSG:4326 BBOX is not consistent among these servers: the actual adapters use provider-specific orders. Never transpose a BBOX without testing a known point.

C

Page and test the circle

Use count and startIndex; stop after a short page. The BBOX only reduces the remote search area. The code then keeps parcels whose computed centre is within the requested radius and deduplicates IDs. Spain's vector route instead geometrically clips its polygons.

D

Separate observed and inferred

A declared culture code is stronger evidence than a generic land-use class. For forest/unknown records, the application may consult OSM tags and Dynamic World. Preserve the original source and the inferred/declared status with each result.

Concrete BBOX example

For an illustrative centre at latitude 48.8566, longitude 2.3522, radius 2.5 km, the approximation used by the adapters produces south 48.834077, west 2.317968, north 48.879123, east 2.386432. France sends 2.317968,48.834077,2.386432,48.879123,EPSG:4326. Wallonia and Emilia-Romagna reverse the coordinate pairs.

Minimal WFS client, with a provider-specific BBOX
async function readPages({ baseUrl, typeName, outputFormat, bbox, pageSize = 500 }) {
  const all = [];
  for (let startIndex = 0; startIndex < 20000; startIndex += pageSize) {
    const q = new URLSearchParams({
      service: 'WFS', version: '2.0.0', request: 'GetFeature',
      typeNames: typeName, outputFormat, srsName: 'EPSG:4326',
      count: String(pageSize), startIndex: String(startIndex), bbox
    });
    const upstream = baseUrl + '?' + q.toString();
    const response = await fetch('/proxy?url=' + encodeURIComponent(upstream));
    if (!response.ok) throw new Error('Source HTTP ' + response.status);
    const page = await response.json();
    const features = Array.isArray(page.features) ? page.features : [];
    all.push(...features);
    if (features.length < pageSize) break;
  }
  return all;
}

This is a didactic template for GeoJSON-producing sources. German GML and ArcGIS REST need their separate parsers and query parameters, shown in the Germany chapter. Production code should add timeouts, cache, response-size controls, cancellation and provider-specific maximum pages.

The normalized parcel object

The web app converts remote schemas into comparable records. The example below is illustrative, not a captured API response; the keys match fields used by the model.

Schematic internal record
{
  "id": "FR_example-123", "countryCode": "FR",
  "source": "RPG Geoplateforme WFS",
  "lat": 48.851, "lng": 2.349,
  "displayName": "Colza hiver", "cropKey": "CZH",
  "usoCode": "TA", "cultivoEspecifico": "Colza hiver",
  "superficieNum": 1.8, "superficie": "1.80 ha",
  "regadio_secano": "SECANO",
  "valorApicola": 0.73
}

valorApicola is a local, season-sensitive ranking score, not measured honey yield. cropKey is the bridge to a country botanical catalogue. If a provider lacks an area value, some current adapters calculate it from geometry; Sweden, France and Italy can fall back to 1 ha. A receiving team should flag that as estimated rather than silently treating it as surveyed area.

Credentials, costs and safe handoff

The public geospatial URL templates are safe to explain. The ability to charge your account or consume your quota comes from credentials, project settings and access to your own backend. This guide deliberately contains none of those.

ConnectionHow this repository authenticatesWhat the recipient must supplyCost or access point to check
Country WMS/WFS, ArcGIS and SIGPAC public endpointsNo application key is embedded in the request construction.Their own client/server, attribution and provider terms.Public access does not automatically permit redistributing raw data or ignoring limits.
Google Earth Engine / Dynamic WorldPrivate service-account JSON on the Node server; never sent to the browser.Their own Google Cloud/Earth Engine project and identity.Commercial use may require a paid Earth Engine setup; compute quotas are per project. Google access guide.
Open-Meteo forecastThe code calls the public api.open-meteo.com endpoint without a key.Their own appropriate use agreement if commercial.Open-Meteo says its free API is for non-commercial use; commercial access has a separate keyed endpoint. Pricing and terms.
Nominatim / OSM public map servicesNo key in these request URLs.Their own usage policy compliance or suitable provider.The public Nominatim service limits heavy use and asks for attribution and an identifying user agent/referer. Usage policy.

Protect the billable backend, not only the JSON key. In the current application, Dynamic World requests reach Earth Engine through the application's Node endpoints. Publishing your production backend's address or giving unrestricted access to those endpoints could let others use your project indirectly. This handoff uses YOUR_BACKEND placeholders and shows no real deployment host. A receiving team should run its own backend and add authentication/rate limits to its Earth Engine routes before public deployment.

Safe to share

Public service base URLs, public layer names, parameter names, response field names, the high-level data flow and open-source integration examples.

Not included

Private-key contents, API keys, bearer tokens, cookies, Google project IDs, billing identifiers, your deployed server IP/host or private user data.

Implementation status

This explains the current source code. It does not claim every remote URL is healthy today, nor that every provider grants every downstream use.

ES

Spain · SIGPAC / MAPA

National agricultural parcel data, with a fast vector route and older fallbacks.

Primary calculationHubCloud vector GeoJSON tiles
Map displaySIGPAC WMS
CoverageSpain; regional analysis also implemented

Visual connection: Leaflet requests SIGPAC WMS version 1.3.0 as transparent PNG. The layer names are AU.Sigpac:recinto, AU.Sigpac:cultivo_declarado and AU.Sigpac:e_paisaje. A clicked pixel can be queried with WMS GetFeatureInfo through /proxy.

Calculation connection: the browser calls its own backend GET /sigpac-parcels-in-radius. That backend requests HubCloud recinto and cultivo_declarado GeoJSON tiles at zoom 15, joins them by SIGPAC identity, loads cod_producto.json and cod_uso_sigpac.json for labels, clips polygons to the circle with Turf, and returns parcel area and crop data.

Preferred request to your own backend
GET /sigpac-parcels-in-radius?lat=40.4637&lng=-3.7492&radiusKm=2.5&minAreaM2=1000&strategy=stratified&maxParcels=600&minPerStratum=20&seedMode=deterministic

Upstream tile template:
https://sigpac-hubcloud.es/mvt/{recinto|cultivo_declarado}@3857@geojson/15/{x}/{y}.geojson

Code tables:
https://sigpac-hubcloud.es/codigossigpac/cod_producto.json
https://sigpac-hubcloud.es/codigossigpac/cod_uso_sigpac.json

The endpoint returns parcels, sampling, counts, tile errors and clipped area. Default sampling is stratified when needed; strategy=all requests every matching parcel. The current backend caps the circle radius at 10 km and rejects requests that need more than 160 z15 tiles.

Fallback and scope. If the vector route fails, the app tries /parcels-in-radius: Catastro INSPIRE WFS supplies geometry and SIGPAC WMS GetFeatureInfo enriches centroids. A separate grid mode samples WMS points. Catastro geometry is not a crop declaration. Spain's larger regional view uses /sigpac-regional-heatmap and /regional-progress/:jobId.

What each Spanish request contributes

RequestInputOutput the app usesPurpose
HubCloud recinto z15 GeoJSON tilez/x/y tile coordinatesPolygon, uso_sigpac, superficie, coef_regadio, SIGPAC identity columnsParcel geometry and general agricultural use.
HubCloud cultivo_declarado z15 GeoJSON tileThe same tile coordinatesparc_producto, parc_supcult, parc_sistexp, exp_ano, SIGPAC identity columnsDeclared crop and cultivation system, when present.
HubCloud code tablescod_producto.json, cod_uso_sigpac.jsonCode-to-description mapsTurn numerical/short codes into readable product and use names.
Catastro INSPIRE WFS fallbackcp:CadastralParcel and a BBOXGML parcel outline and referenceGeometry if HubCloud vector route is unavailable.
SIGPAC WMS GetFeatureInfo fallbackProjected BBOX and image pixel i/jHTML for recinto plus cultivo_declaradoEnrich a Catastro centroid with agricultural use/crop.

The seven-part SIGPAC key is provincia:municipio:agregado:zona:poligono:parcela:recinto. The server uses it to join recinto and declared-crop tiles. The same complete polygon can be repeated in adjacent tiles, so it keeps the largest clipped intersection for each key rather than summing duplicates. Crop data is absent for some recintos; the model then uses a lower-confidence land-use profile or enrichment.

Detailed SIGPAC fallback requests
Catastro geometry:
GET https://ovc.catastro.meh.es/INSPIRE/wfsCP.aspx
  ?service=WFS&request=GetFeature&typenames=cp:CadastralParcel
  &srsname=EPSG:4326&bbox={south},{west},{north},{east},EPSG:4326
  &maxfeatures=800

SIGPAC WMS attribute lookup (the browser sends the URL through /proxy):
GET https://sigpac-hubcloud.es/wms
  ?service=WMS&version=1.3.0&request=GetFeatureInfo
  &layers=AU.Sigpac:recinto,AU.Sigpac:cultivo_declarado
  &query_layers=AU.Sigpac:recinto,AU.Sigpac:cultivo_declarado
  &info_format=text/html&crs=EPSG:3857
  &bbox={projectedWest},{projectedSouth},{projectedEast},{projectedNorth}
  &width=256&height=256&i=128&j=128

The GetFeatureInfo bounding box is in metres in EPSG:3857, centred on the queried point; its image pixel is 128/128. The backend Catastro fallback defaults to 800 features (hard cap 2,000) and clips them to the circle. The constant used by this fallback requests cultivo_declarado; an adjacent code comment calls it linea_declaracion, so the constant is authoritative here.

How a returned Spanish parcel enters the model

1

Decode + clip. Convert any 3857 tile geometry to longitude/latitude; intersect with a 128-step apiary circle and drop pieces below minAreaM2.

2

Join + classify. Join crop and recinto on the seven-part key; map uso_sigpac and parc_producto through the public code tables. Convert parc_supcult from m² to ha and infer irrigation from coef_regadio/parc_sistexp.

3

Sample transparently. With strategy=stratified, sample by land-use stratum when the parcel count exceeds the target, attach sampling_weight and retain the deterministic seed. With strategy=all, each parcel has weight 1.

4

Estimate. Feed clipped hectares, crop/use, irrigation, coordinates and source confidence to honey_model.js. The model estimates weekly floral potential, then aggregates at apiary scale.

Response to handle: n_parcels_total_in_radius, n_parcels_returned, n_tile_errors, coverage_of_circle_pct, sampling and parcels. A non-zero tile-error count means the output may be incomplete even if the HTTP request succeeds. HTTP 413 means the chosen radius would request too many tiles. The server caches tiles for six hours and code tables for one day.

Regional route: /sigpac-regional-heatmap?lat=&lng=&radiusKm=&gridKm=&jobId= divides a larger circle into subareas and returns aggregated cells instead of thousands of parcel records. It is a separate Spain-only analysis path; the other country adapters do not expose that regional function.

SE

Sweden · Jordbruksverket

Agricultural blocks from a public INSPIRE WFS.

Feature serviceJordbruksverket WFS 2.0
Visual serviceWMS 1.3.0
Typical fieldsagoslag, areal, blockid

WFS endpoint: http://epub.sjv.se/inspire/inspire/wfs. Query inspire:senaste_arslager_block; request application/json, EPSG:4326 and a longitude–latitude bounding box. The adapter asks for 500 features per page, up to 40 pages, through /proxy.

WFS request shape
GET http://epub.sjv.se/inspire/inspire/wfs
  ?service=WFS&version=2.0.0&request=GetFeature
  &typeNames=inspire:senaste_arslager_block
  &outputFormat=application/json&srsName=EPSG:4326
  &count=500&startIndex=0
  &bbox={west},{south},{east},{north},EPSG:4326

Read agoslag as the land-use label, areal as hectares and blockid as the stable key. Swedish terms are mapped to a canonical cropKey, a broad usoCode, and a month-sensitive beekeeping score. Leaflet displays inspire:senaste_arslager_block and inspire:senaste_arslager_skifte from the matching WMS endpoint.

Interpretation: the prediction query currently uses the block layer, even though a skifte layer can be displayed. The two Swedish URLs use http in the code, so a team deploying an HTTPS page must account for mixed-content restrictions and route these requests through a secure server endpoint.

Fields, translation and pagination

Remote fieldNormalized fieldRule in the adapter
blockidid = "SE_" + blockidDeduplicates records across pages.
agoslag (fallback KATEGORI)displayName, cropKey, usoCodeText matching: oilseed/rapeseed → raps; clover → klover; grassland → vall; woodland → FO.
areal (fallback area)superficieNum, superficieParsed as hectares by the current code; a missing/invalid value becomes 1.
region_kod, kategoriregionKod, kategoriRetained for provenance/display.
GeoJSON geometrylat, lngPolygon centre is computed; outside-circle centres are removed.

The adapter caches by rounded centre and radius, fetches 500 records per page, pauses briefly between full pages, and stops at an empty/short page or after 40 pages. On a WFS failure it logs the error and returns the records already collected; therefore a non-empty result can still be incomplete. A receiving implementation should expose an incomplete flag rather than treating partial pages as a full census.

Illustrative Swedish mapping (values are examples)
Remote feature.properties:
{ "blockid": "example-42", "agoslag": "oljeväxter", "areal": 2.4 }

Normalized parcel:
{ "id": "SE_example-42", "countryCode": "SE",
  "displayName": "oljeväxter", "cropKey": "raps",
  "usoCode": "TA", "superficieNum": 2.4,
  "source": "Jordbruksverket WFS" }

Map click: when a Swedish overlay is visible, a tiny BBOX around the clicked coordinate requests up to 10 features from the visible block and/or skifte types. That click lookup is separate from the 500-record prediction query.

Provider-published HTTPS option. The Jordbruksverket GIS page publishes https://epub.sjv.se/inspire/inspire/wfs and https://epub.sjv.se/inspire/inspire/wms. The current source uses http://. A new integration should prefer the provider's published HTTPS addresses after checking capabilities and response parity. The block database is agricultural-support data, not a direct measure of flowering or nectar.

FR

France · IGN Géoplateforme RPG

Graphical agricultural parcels and a culture-code dictionary.

Feature serviceGéoplateforme WFS 2.0
Parcel layerRPG.LATEST:parcelles_graphiques
Dictionary layerRPG.LATEST:codes_cultures

The adapter queries https://data.geopf.fr/wfs via /proxy. Before parcel retrieval it fetches up to 500 entries from RPG.LATEST:codes_cultures to turn short crop codes into labels; a local code dictionary remains available if that call fails. Parcel pages are 500 features, up to 40 pages.

Parcel request shape
GET https://data.geopf.fr/wfs
  ?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature
  &TYPENAMES=RPG.LATEST:parcelles_graphiques
  &outputFormat=application/json&SRSNAME=EPSG:4326
  &COUNT=500&startIndex=0
  &BBOX={west},{south},{east},{north},EPSG:4326

Map code_cultu to the crop code, cat_cult_p to category, surf_parc (or sf_adm_de) to hectares and id_parcel to identity. The crop code is the French cropKey used by the floral catalogue. WMS overlays at https://data.geopf.fr/wms-r/wms use LANDUSE.AGRICULTURE.LATEST and IGNF_RPG_PARCELLES-AGRICOLES-CATEGORISEES_2024.

Dictionary, fields and a record through the adapter

Culture-code dictionary request
GET https://data.geopf.fr/wfs
  ?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature
  &TYPENAMES=RPG.LATEST:codes_cultures
  &outputFormat=application/json&COUNT=500
Remote valueLocal useImportant handling
code_cultucropKeyResolve its display label through the remote dictionary; use the bundled dictionary if lookup fails.
cat_cult_pCrop category and broad usoCodeKeep alongside the exact culture code; it is less specific than the code.
surf_parc, fallback sf_adm_desuperficieNum in haThe code defaults to 1 ha if parsing fails. A copy should flag this imputation.
id_parcel, fallback iup/gidStable parcel IDDeduplicate across pages; a coordinate-plus-code key is the final fallback.
GeoJSON polygonCentre lat/lngAccept only a centre inside the apiary circle.

The adapter caches requests by rounded location and radius. A full page triggers the next startIndex; a short page stops the loop. Errors can leave a partial result, so retain the fetched-page count and communicate incompleteness. RPG.LATEST and the WMS layer labelled 2024 need independent version checks: the visual layer's year does not prove the feature layer has the same vintage.

Illustrative mapping, not a captured record
Remote feature.properties:
{ "id_parcel": "example-123", "code_cultu": "CZH",
  "cat_cult_p": "COLZA", "surf_parc": 1.8 }

Normalized parcel:
{ "id": "FR_example-123", "countryCode": "FR",
  "cropKey": "CZH", "superficieNum": 1.8,
  "source": "RPG Geoplateforme WFS" }

Map interaction: the WMS paints the visible RPG layer; a clicked location uses a small WFS BBOX to retrieve nearby feature attributes. For a new build, start with the provider's Géoplateforme WFS instructions and GetCapabilities, then confirm that the requested type and JSON format still exist.

IT

Italy · national Catasto, regional land use

Two different roles: national display and Emilia-Romagna calculation.

National displayAgenzia delle Entrate Catasto WMS
CalculationEmilia-Romagna land-use WFS
LimitDetailed analysis only in Emilia-Romagna

The national Catasto WMS exposes CP.CadastralParcel for parcel outlines. The adapter explicitly substitutes EPSG:4258 in the generated tile URL. Cadastral outlines contain no dependable crop identity for this model.

For the estimate, query Emilia-Romagna WFS layer _020_uso_suolo_ed2023 through /proxy. The code uses WFS 2.0, outputFormat=geojson, 500-feature pages and a latitude–longitude bounding box. The query is attempted only when the chosen circle overlaps the configured Emilia-Romagna bounds.

Regional calculation request
GET http://servizigis.regione.emilia-romagna.it/wfs/uso_del_suolo
  ?service=WFS&version=2.0.0&request=GetFeature
  &typeNames=_020_uso_suolo_ed2023
  &outputFormat=geojson&srsName=EPSG:4326
  &count=500&startIndex=0
  &bbox={south},{west},{north},{east},EPSG:4326

Map DESCR to the land-use description, SIGLA to the class code, HECTARES to area and OBJECTID to identity. The text classifier makes the Italian cropKey; non-productive land is scored very low. The land-use overlay is itself drawn from WFS GeoJSON for the visible map area.

Coverage rule: outside the Emilia-Romagna query window the app raises an explicit coverage error. Piemonte's agricultural WMS is mentioned in the UI but is not an integrated analytical source. The regional WFS URL uses http in the source code; use a secure server-side relay for an HTTPS deployment.

Connection roles and field mapping

InputWhat it suppliesWhat it cannot tell us
National Catasto WMS CP.CadastralParcelRendered cadastral parcel outlines in EPSG:4258Declared crop or flowering potential; the WMS image is not a crop feature census.
Emilia-Romagna WFS _020_uso_suolo_ed2023Regional land-use polygons and class attributesNationwide coverage or a farmer's current crop declaration.
WFS propertyNormalized useRule
SIGLAClass keyRetain original short code for traceability.
DESCRdisplayName, cropKeyText classifier maps recognized land-use words to the Italian floral catalogue.
HECTARES or SHAPE.AREAsuperficieNumUse hectares directly, or divide square metres by 10,000; an invalid value defaults to 1 ha in the current adapter.
OBJECTID or FIDParcel IDDeduplicate features across 500-record pages, up to 40 pages.
GeoJSON geometryPolygon centreRetain a record only when its centre falls inside the circle.
Illustrative land-use translation
Remote feature.properties:
{ "OBJECTID": 123, "SIGLA": "SEMIN", "DESCR": "Seminativi",
  "HECTARES": 2.7 }

Local interpretation:
{ "id": "IT_123", "displayName": "Seminativi",
  "superficieNum": 2.7, "source": "Regione Emilia-Romagna WFS",
  "evidence": "regional land-use class" }

Version to revisit. The code hard-codes a 2023-edition feature type. The regional catalogue also publishes a newer type, portale_uso_del_suolo:_023_uso_suolo_ed2025, on the same WFS family. That is a documented migration candidate, not an integrated or schema-validated replacement. Discover its exact type in GetCapabilities, compare fields and geometry, then change the adapter deliberately.

BE

Belgium · Flanders and Wallonia

Two regional LPIS services, two schemas, two bounding-box conventions.

FlandersDigitaal Vlaanderen WFS + WMS
WalloniaSPW / SIGeC WFS
Query behaviorBoth regions queried for a selected circle
RegionFeature endpoint and typeBBOXCrop / area / ID
Flandersgeo.api.vlaanderen.be/Landbgebrperc/wfs
Landbgebrperc:Lbgebrperc
west,south,east,north
application/json
LBLHFDTLT / GRAF_OPP ÷ 10000 / UIDN
WalloniaSIGeC ArcGIS WFS
SIGEC_PARC_AGRI_ANON:Parcelles_agricoles___2023_
south,west,north,east
GEOJSON
CULT_NOM / SURF_HA / OBJECTID

Both requests use WFS 2.0, EPSG:4326, count=500 and startIndex; each regional loop allows up to 30 pages. Flanders also supplies GEWASGROEP and HFDTLT; Wallonia supplies GROUPE_CULT and CULT_COD. The adapter translates Dutch and French crop names into one Belgian crop catalogue and de-duplicates by region plus ID.

Same operation, different axis order
Flanders:
GET https://geo.api.vlaanderen.be/Landbgebrperc/wfs?service=WFS&version=2.0.0&request=GetFeature&typeNames=Landbgebrperc:Lbgebrperc&outputFormat=application/json&srsName=EPSG:4326&count=500&startIndex=0&bbox={west},{south},{east},{north},EPSG:4326

Wallonia:
GET https://geoservices.wallonie.be/arcgis/services/WFS/SIGEC_PARC_AGRI_ANON/MapServer/WFSServer?service=WFS&version=2.0.0&request=GetFeature&typeNames=SIGEC_PARC_AGRI_ANON:Parcelles_agricoles___2023_&outputFormat=GEOJSON&srsName=EPSG:4326&count=500&startIndex=0&bbox={south},{west},{north},{east},EPSG:4326

For visual display, Flanders has ALV WMS layer LbGebrPerc2023. The Wallonia overlay is painted from returned WFS GeoJSON because the chosen MapServer does not expose a WMS in this implementation.

Normalize the two regional schemas separately

MeaningFlanders fields and ruleWallonia fields and rule
Crop descriptionLBLHFDTLT is preferred; GEWASGROEP gives the group and HFDTLT the crop code.CULT_NOM is preferred; GROUPE_CULT and CULT_COD support classification.
Area in hectaresGRAF_OPP / 10000 (square metres to hectares), fallback OPPERVL, then geometric area.SURF_HA, fallback geometric area.
IdentityUIDN, fallback OIDN/ALVID.OBJECTID, fallback GmlID.
Geometry filterCompute polygon centre, discard outside-circle centres, deduplicate with a region-prefixed key.

The adapter translates Dutch and French names to its own Belgian cropKey and usoCode; those keys point to web/data/melliferous_be.js. It queries both services rather than preselecting one region, so a circle near the regional boundary can receive both. The result contains an adapter-level census annotation; it is not proof that the providers returned a complete census when a page failed.

Illustrative cross-region normalization
Flanders remote: { "UIDN": "example-fl", "LBLHFDTLT": "Koolzaad",
                   "GRAF_OPP": 18000 }
Flanders local:  { "countryCode": "BE", "superficieNum": 1.8,
                   "displayName": "Koolzaad", "region": "Vlaanderen" }

Wallonia remote: { "OBJECTID": "example-wa", "CULT_NOM": "Colza",
                   "SURF_HA": 1.8 }
Wallonia local:  { "countryCode": "BE", "superficieNum": 1.8,
                   "displayName": "Colza", "region": "Wallonie" }

Wallonia migration required. The integrated WFS type is a 2023 legacy parcel layer. Wallonia's official service notice says the older anonymous agricultural-parcel services are being withdrawn by the end of 2026 as a newer SIGeC model replaces them. The new dataset catalogue covers 2024 onward. The application has not been migrated: obtain the new capabilities, feature type and field schema, then update the Wallonia mapping and check attribution and reuse terms before deployment.

Optional provider route: Digitaal Vlaanderen also publishes an OGC API Features collections endpoint. It is a possible modern alternative for a new client, not the route this repository currently calls.

DE

Germany · regional InVeKoS

One adapter dispatches to different Land services; there is no national WFS in the implementation.

The code defines a REGIONS table with geographical bounds and a preferred parcel source (falling back to a reference block). It selects regions intersecting the apiary's bounding box, reads at most 12 pages of 1,000 features per region, and normalizes WFS GeoJSON, WFS GML or ArcGIS REST output to WGS84 GeoJSON. Each row below is an actual configured source.

Land / areaPreferred requestType / methodWhat the adapter reads
North Rhine-WestphaliaNRW WFSumwelt_lwk_eufoerderung:Beantragte_und_als_foerderfaehig_festgestellte_Teilschlaege_in_NRW · GeoJSONCODE_TXT, AREA_HA, ID
Lower SaxonySLA WFSagrar_ref:feldbloecke · JSON blocksbnk_txt, flaeche, flik
Baden-WürttembergFIONA WFSlw:v_fiona_flaecheninformation · JSONBezeichnung, FlaecheInHa, object_id
HesseHesse WFSlawi:Landwirtschaftliche Parzellen 2024 · JSONmainCrop, declaredArea, id
Mecklenburg-VorpommernMV WFSmv:feldbloecke · JSON blocksbodennutzu, groesse_p, fbid
SaxonySaxony WFSinvekos:AgriculturalParcel · GeoJSON, coordinates swappedmainCrop, declaredArea, OBJECTID
Saxony-AnhaltArcGIS MapServer /0/query?f=geojson · ArcGIS RESTCLASS_CODE, geometric area, ID_LOCALID
Bremen / HamburgSLA INSPIRE WFSagrar_ref_inspire:LPIS_AgriculturalArea · JSONname, geometric area, id
BavariaBavaria WFSlpis:AgriculturalArea · GML/XMLagriculturalAreaType, geometric area, identifier
Brandenburg / BerlinBB WFSrefbb:Feldblock · GML/XML blocksHBN_KAT, FL_BRUTTO_HA, FB_ID
SaarlandSaarland WFSelu:ExistingLandUseObject · GML/XMLname, area/FLIK parsed from description
German dispatcher: three request forms
// JSON WFS (type, format and BBOX order come from the selected Land row)
GET {base}?service=WFS&version=2.0.0&request=GetFeature&typeNames={type}&outputFormat={format}&srsName=EPSG:4326&count=1000&startIndex=0&bbox={providerSpecificBbox}

// GML-only WFS (Bavaria, Brandenburg/Berlin, Saarland)
GET {base}?service=WFS&version=2.0.0&request=GetFeature&typeNames={type}&count=1000&startIndex=0&srsName=urn:ogc:def:crs:EPSG::4326&bbox={south},{west},{north},{east},urn:ogc:def:crs:EPSG::4326

// Saxony-Anhalt ArcGIS REST
GET {base}/query?where=1%3D1&outFields=*&f=geojson&outSR=4326&geometryType=esriGeometryEnvelope&inSR=4326&spatialRel=esriSpatialRelIntersects&geometry={west},{south},{east},{north}&resultRecordCount=1000&resultOffset=0

The adapter uses provider-specific field extractors, swaps Saxony's returned coordinates, parses GML for three providers and computes area from geometry when no usable area field exists. It turns German/INSPIRE crop labels into the German cropKey and monthly score. Its map overlays are drawn from normalized GeoJSON, rather than one country-wide WMS.

The decisions inside the dispatcher

Provider groupBBOX order in the current codeResponse handling
NRW, Mecklenburg-Vorpommern, Saxonysouth,west,north,eastWFS GeoJSON; Saxony swaps each returned coordinate pair before geometry calculations.
Lower Saxony, Baden-Württemberg, Hesse, Bremen, Hamburgwest,south,east,northWFS JSON; configured property readers select crop, area and ID.
Bavaria, Brandenburg/Berlin, Saarlandsouth,west,north,east with the full EPSG URNWFS GML/XML; the parser reads posList and converts latitude/longitude to GeoJSON longitude/latitude.
Saxony-AnhaltArcGIS envelope west,south,east,northArcGIS REST GeoJSON; use resultOffset rather than WFS startIndex.
Example Land: NRW parcel to model (illustrative values)
Remote properties:
{ "ID": "example-7", "CODE_TXT": "Raps",
  "USE_TXT": "Ackerland", "AREA_HA": 1.6 }

Adapter output:
{ "id": "DE_NRW_P_example-7", "countryCode": "DE",
  "region": "Nordrhein-Westfalen", "cropKey": "raps",
  "usoCode": "TA", "superficieNum": 1.6,
  "source": "InVeKoS Nordrhein-Westfalen" }

The source choice is one per Land: prefer a configured parcel source, otherwise use the block source. The adapter does not merge a parcel layer with its block fallback, which avoids counting both representations for the same area. A page error stops only that source's loop; a full final page at the 12-page cap can leave undiscovered records. Expose source, fetched count and truncation/error state in a fresh implementation.

GML limit: the in-repository parser is deliberately small. It reads posList rings and simple properties, but may not preserve every complex GML geometry relationship. For a production reimplementation, use a full GML parser and validate a known polygon, area and axis order for each service.

Coverage is 13 of 16 Länder in the application's configured regions: the 11 source rows represent Bremen and Hamburg separately, and the Brandenburg source also covers Berlin. Rhineland-Palatinate, Schleswig-Holstein and Thuringia are not connected for detailed analysis. Some connected areas expose only reference blocks or broad land-use classes, so crop specificity varies by Land. The opening comment in web/countries/de/index.js still says “9 Länder”; the current REGIONS table and UI list 13.

Shared services that enrich the estimate

01

Google Earth Engine / Dynamic World

The Node server authenticates with a Google Earth Engine service-account JSON stored locally as server/.private-key.json. It queries GOOGLE/DYNAMICWORLD/V1. GET /dw-map supplies map tiles; GET /dynamic-world-point?lat=&lng=&windowDays= or POST /dynamic-world-batch classify uncertain parcel centres. The batch accepts {"points":[{"lat":40.4,"lng":-3.7}],"windowDays":90}, up to 1,000 points. Teams need their own Earth Engine project and service account.

02

OpenStreetMap / Overpass

The server's GET /osm-forest?lat=&lng= calls https://overpass-api.de/api/interpreter for forest tags and keeps a persistent local cache. If Overpass fails, it can return an unavailable/empty result. The map uses OSM raster tiles; address search and reverse geocoding call Nominatim separately.

03

Open-Meteo

GET /climate?lat=&lng= calls https://api.open-meteo.com/v1/forecast for 14 daily values: minimum, maximum and mean temperature, mean relative humidity, maximum wind speed and precipitation. The backend turns these into a daily and average flight-suitability score. It is a forecast input, not a crop-parcel source.

04

Bioregion and floral catalogues

GET /bioregion is an application backend endpoint for regional context. The country catalogues live in web/data/melliferous_*.js; Spanish species data is in melliferous_species.js. These are local application data and logic, not third-party API calls.

Credential handoff: no private key is embedded in this document. The public geodata request shapes are shown in full. The Earth Engine service-account file is a credential that each receiving team must create and keep on its own server.

Supporting requests and their exact role

Local route or public serviceParameters / response usedPlace in the estimate
GET /dynamic-world-pointlat, lng, windowDays (default 90; allowed 7–365). The server reads mean class probabilities from GOOGLE/DYNAMICWORLD/V1 at approximately 10 m.Refine uncertain land-use/forest evidence. Point results have a seven-day cache.
POST /dynamic-world-batch{"points":[{"lat":40.4,"lng":-3.7}],"windowDays":90}; server maximum 1,000 points, concurrency 3. The browser limits its enrichment selection to about 300 uncertain parcels.Batch the same classification without one browser request per parcel.
GET /dw-maplat, lng, radiusKm, optional start/end/prob; returns an Earth Engine map tile template and transient token.Map visualization. Treat the returned tile token as short-lived access material; do not publish a captured response.
GET /osm-forestlat, lng, optional r; Overpass looks for forest/wood ways and relations and reads leaf_type/species tags.Use tagged tree evidence for forest profiles. A failed request can return source: unavailable, not proof of no forest.
GET /climatelat, lng; Open-Meteo daily variables for a 14-day forecast; local output contains daily and mean 0–100 suitability scores.Short-range bee-flight context, separate from annual floral capacity.
GET /bioregionlat, lng, optional source/country; intersects locally cached EEA/Spanish GeoJSON.Choose regional botanical context. The route does not make a fresh third-party request per point.
Public Open-Meteo call made by the backend
GET https://api.open-meteo.com/v1/forecast
  ?latitude={lat}&longitude={lng}
  &daily=temperature_2m_min,temperature_2m_max,temperature_2m_mean,
         relative_humidity_2m_mean,wind_speed_10m_max,precipitation_sum
  &timezone=auto&forecast_days=14

From a normalized parcel to kilograms

1

Choose a botanical profile. The declared crop has priority. OSM forest tags may supply a forest profile; Dynamic World helps reject incompatible inferred uses. Otherwise the model infers species from broad land use, and marks that profile as inferred.

2

Calculate weekly potential. For each matching species, combine hectares, profile coverage, species potential divided over flowering weeks, weekly intensity, irrigation factor, distance factor 1 − distanceMetres / 10000 and any inferred-profile attenuation. Spain's stratified sample adds sampling_weight.

3

Aggregate by apiary. Sum the 52 weekly vectors; cap each species and consecutive flowering window at 500 kg, then apply the model's region coefficient and Janssens regression. The 12-hive default is an application assumption; supply the real hive count for a meaningful per-hive division.

This is an estimate built from remote landscape data and local assumptions. The external APIs do not return measured nectar output or harvested honey. See web/honey_model.js for the full equations, species profiles and sensitivity bands.

Worked example: recreate a French query

This example is intentionally synthetic. It shows how another team can reproduce the connection and data transformation without any SiBeela credential, backend address or private observation.

1

Choose a centre. Latitude 48.8566, longitude 2.3522, radius 2.5 km. Calculate the BBOX: west 2.317968, south 48.834077, east 2.386432, north 48.879123.

2

Resolve culture names. Request the RPG.LATEST:codes_cultures type once and map its culture codes to descriptions; keep the local dictionary as a fallback.

3

Page parcels. Request RPG.LATEST:parcelles_graphiques with that BBOX, COUNT=500 and startIndex=0. If 500 features arrive, request startIndex=500. Stop after a shorter page, an error or the adapter's 40-page cap.

4

Validate and normalize. For each polygon, calculate its centre; retain centres within 2.5 km, deduplicate id_parcel, parse surf_parc in hectares and keep code_cultu as cropKey. Record dictionary misses and imputed areas.

5

Estimate and disclose limitations. Match cropKey to the French floral catalogue, calculate 52 weeks of parcel potential, aggregate and report assumptions plus any missing pages. The source year and crop declaration may differ from the current flowering season.

Runnable request construction; use your own relay in a browser
const base = 'https://data.geopf.fr/wfs';
const q = new URLSearchParams({
  SERVICE: 'WFS', VERSION: '2.0.0', REQUEST: 'GetFeature',
  TYPENAMES: 'RPG.LATEST:parcelles_graphiques',
  outputFormat: 'application/json', SRSNAME: 'EPSG:4326',
  COUNT: '500', startIndex: '0',
  BBOX: '2.317968,48.834077,2.386432,48.879123,EPSG:4326'
});
const upstream = `${base}?${q}`;
const response = await fetch(
  'https://YOUR_BACKEND/proxy?url=' + encodeURIComponent(upstream)
);
if (!response.ok) throw new Error(`Source HTTP ${response.status}`);
const { features = [] } = await response.json();
console.log('Features in first page:', features.length);

The placeholder relay must be your own service. For direct server-to-server use, call the public provider URL without a browser proxy. The example's coordinates and records are teaching values; no production request result is embedded here.

Implementation checklist for another team

  1. Choose a country and confirm the selected apiary is inside that adapter's actual analytical coverage.
  2. Use WMS only for map images; use the listed feature endpoint for parcel and crop attributes.
  3. Keep provider-specific typeNames, output format, bounding-box axis order, coordinate correction and field mapping. These details are especially important for Belgium, Italy and Germany.
  4. Page through features and deduplicate on the provider's ID. Then test each polygon centre against the circle; a BBOX alone is rectangular.
  5. Keep source name, original crop label, area, country, region, canonical cropKey and data-quality flags with each normalized parcel.
  6. Use local floral mappings and phenology to turn land use into a potential estimate. Do not treat a land-use score as kilograms of honey by itself.
  7. Prepare caching, timeouts, retry/backoff and a truthful “source unavailable” state. The country's public service can be slow, partial or temporarily offline.
  8. If you use Earth Engine, configure your own service account. Keep secrets on the server and proxy HTTP-only sources through an HTTPS backend.
  9. Protect any billable or quota-limited backend route with authentication, rate limits and request caps. Never give another team access to your existing Earth Engine project or deployed server.
  10. Review the provider's attribution, reuse and rate-limit terms. Replace Wallonia's legacy layer after inspecting the new SIGeC schema; treat Emilia-Romagna's newer layer as a candidate until field mapping is verified.

What the result means. SiBeela estimates a landscape's beekeeping potential from external land-use and environmental data plus its own botanical model. It does not receive a measured honey harvest from any of these APIs, and the forecast is not a guarantee of kilograms per hive.

Source-code map

These local files are the implementation behind the requests and limits above. The HTML example sibeela_explicacion_v2.html supplied the visual language of this guide.

Signed, Eduardo Marcos Alejos
Senior Programmer and Data Scientist · BeeLife
BeeLife European Beekeeping Coordination