<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Parcelle</title>
    <description>The latest articles on DEV Community by Parcelle (@parcelle).</description>
    <link>https://dev.to/parcelle</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4159365%2F4c98d9fd-0cd3-4eeb-8d76-b6e1b2202ba4.jpg</url>
      <title>DEV Community: Parcelle</title>
      <link>https://dev.to/parcelle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/parcelle"/>
    <language>en</language>
    <item>
      <title>I spent a week on Switzerland's open geodata APIs. Here are the four traps.</title>
      <dc:creator>Parcelle</dc:creator>
      <pubDate>Sat, 03 Oct 2026 09:25:15 +0000</pubDate>
      <link>https://dev.to/parcelle/i-spent-a-week-on-switzerlands-open-geodata-apis-here-are-the-four-traps-21i9</link>
      <guid>https://dev.to/parcelle/i-spent-a-week-on-switzerlands-open-geodata-apis-here-are-the-four-traps-21i9</guid>
      <description>&lt;p&gt;I'm building a side project called &lt;a href="https://ma-parcelle.ch" rel="noopener noreferrer"&gt;Parcelle&lt;/a&gt;. It's a site for landowners in French-speaking Switzerland: our goal is to give landowners access to important public information that will govern what they can  and cannot develop on their land, and the tools to speak eye to eye with real estate developers and architects. &lt;/p&gt;

&lt;p&gt;So, we decided to build an easy "plot lookup" system: you type your address, and it tells you what the public registers say about your plot. Zoning, legal restrictions, building data, links to the official documents. You can find an example here: &lt;a href="https://ma-parcelle.ch/fr/parcelle/CH314566837512" rel="noopener noreferrer"&gt;https://ma-parcelle.ch/fr/parcelle/CH314566837512&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The data is public and free. There's no API key anywhere in this post. What took me a week was working out how to use it, because the official docs list the endpoints and say nothing about the ways you'll get them wrong.&lt;/p&gt;

&lt;p&gt;Four of those cost me most of the week. I've only tested this against one canton out of twenty-six, and I'll come back to why that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The starting point
&lt;/h2&gt;

&lt;p&gt;Switzerland runs a federal geodata API at &lt;code&gt;api3.geo.admin.ch&lt;/code&gt;. No registration, no key, no quota I've hit so far. It fronts hundreds of layers: zoning, noise maps, geology, solar potential, public transport, the federal building register.&lt;/p&gt;

&lt;p&gt;An address lookup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://api3.geo.admin.ch/rest/services/api/SearchServer
    ?searchText=Avenue de la Gare 1 Lausanne
    &amp;amp;type=locations
    &amp;amp;origins=address
    &amp;amp;sr=2056
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one works first time. Then it gets interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 1: &lt;code&gt;x&lt;/code&gt; is the northing
&lt;/h2&gt;

&lt;p&gt;The response looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Avenue de la Gare 1 &amp;lt;b&amp;gt;1003 Lausanne&amp;lt;/b&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1152019.625&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2538509.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;46.5166&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.6374&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're like me, you read &lt;code&gt;x, y&lt;/code&gt; and you reach for &lt;code&gt;geometry=x,y&lt;/code&gt; in the next call.&lt;/p&gt;

&lt;p&gt;Don't. In this API &lt;code&gt;x&lt;/code&gt; is the northing and &lt;code&gt;y&lt;/code&gt; is the easting. Every downstream endpoint wants &lt;code&gt;geometry={easting},{northing}&lt;/code&gt;, which means you pass &lt;code&gt;geometry={y},{x}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The part that ate my afternoon is that swapping them doesn't throw. Swiss LV95 coordinates sit roughly between 2.4 and 2.8 million east, and 1.0 and 1.3 million north. Swap them and you get a point that's numerically plausible and geographically nowhere. The API returns an empty result set, and you spend an hour assuming your layer name is wrong.&lt;/p&gt;

&lt;p&gt;I now have a unit test whose only job is to assert that a known Lausanne address comes back with a commune called Lausanne.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 2: one point, a hundred and forty rows
&lt;/h2&gt;

&lt;p&gt;I wanted the commune and canton for a coordinate. There's a layer for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET .../MapServer/identify
    ?geometry=2538509,1152019
    &amp;amp;geometryType=esriGeometryPoint
    &amp;amp;layers=all:ch.swisstopo.swissboundaries3d-gemeinde-flaeche.fill
    &amp;amp;tolerance=0&amp;amp;sr=2056&amp;amp;returnGeometry=false
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I expected one result. I got more than 140, several hundred kilobytes of JSON, for a point that sits inside exactly one commune.&lt;/p&gt;

&lt;p&gt;The layer is historical. One feature per year, back to 1850. Lausanne in 1882, Lausanne in 1883, Lausanne in 1884, each with a slightly different area as the municipal boundaries moved.&lt;/p&gt;

&lt;p&gt;The fix is one line, once you know the field exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commune&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;is_current_jahr&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The history is there on purpose. If you ever need to know which commune a parcel belonged to before a merger, this is where you look. It's just a surprise when all you wanted was today's name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 3: the layer that tells you where to go next
&lt;/h2&gt;

&lt;p&gt;This is the good one, and the thing I wish someone had written down.&lt;/p&gt;

&lt;p&gt;Switzerland maintains a cadastre of public-law restrictions on land, the ÖREB cadastre, RDPPF in French. It records what legally constrains a given plot: zoning plans, noise sensitivity, forest boundaries, airport safety zones.&lt;/p&gt;

&lt;p&gt;It isn't a federal service. All 26 cantons run their own. So how do you know which endpoint to call for an arbitrary coordinate?&lt;/p&gt;

&lt;p&gt;There's a layer for that, and you'd never guess it from the name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;layers=all:ch.swisstopo-vd.stand-oerebkataster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query it with a point and you get this, per commune:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"gemeindename"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lausanne"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kanton"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Vaud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bfs_nr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5586&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"oereb_status_fr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cadastre RDPPF introduit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"firmenname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Direction du cadastre et de la géoinformation du Canton de Vaud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url_oereb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://www.rdppf.vd.ch/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"oereb_webservice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.rdppf.vd.ch/ws/RdppfSVC.svc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"info.dgtl@vd.ch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"telefon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"021 316 24 60"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;oereb_webservice&lt;/code&gt; is the field that matters. A federal layer handing you the cantonal API endpoint for any point in the country, along with the office that runs it and whether that commune has the cadastre in production yet. Plenty of them don't.&lt;/p&gt;

&lt;p&gt;I was about a third of the way through hand-writing a lookup table of cantonal portals when I found it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 4: the cantonal endpoints don't agree on paths
&lt;/h2&gt;

&lt;p&gt;With the service URL in hand, the ÖREB spec gives you standard operations. Resolving a coordinate to a federal property identifier works exactly as documented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET {service}/getegrid/json/?EN={easting},{northing}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"Item"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"egrid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CH774594628366"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6177"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"identDN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VD0132000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"Text"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="nl"&gt;"Text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Bien-fonds"&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I went looking for the full extract. The common implementation, &lt;code&gt;pyramid_oereb&lt;/code&gt;, which a number of cantons run, exposes it at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{service}/extract/reduced/json/{egrid}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;So did &lt;code&gt;oereb/extract/reduced/json/{egrid}&lt;/code&gt;. So did every path variant I tried.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I concluded the canton simply didn't publish the extract, wrote that down as a constraint in a technical spec, and moved on. It sat there for two days.&lt;/p&gt;

&lt;p&gt;It does publish it. The path uses a query parameter instead of a path segment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET {service}/extract/json/?EGRID={egrid}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;145 KB of structured JSON. Every restriction on the parcel with its exact area share, and every legal document with a direct PDF link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Theme"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Plans d'affectation (cantonaux/communaux)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AreaShare"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;947&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"PartInPercent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;96.258939734339&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"LegalProvisions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Plan général d'affectation Règlement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"TextAtWeb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.rdppf.vd.ch/ws/utilities/GetDocuments.ashx?..."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I'd do differently: before concluding an endpoint doesn't exist, call &lt;code&gt;{service}/capabilities/json/&lt;/code&gt; and &lt;code&gt;{service}/versions/json/&lt;/code&gt;. Both answered fine on this service while the documented extract path was 404ing. That should have told me the service was alive and I was knocking on the wrong door.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Address to coordinates&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;api/SearchServer?type=locations&lt;/code&gt;, remember &lt;code&gt;x&lt;/code&gt; is north&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Point to commune&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;swissboundaries3d-gemeinde-flaeche.fill&lt;/code&gt;, filter on &lt;code&gt;is_current_jahr&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Point to cantonal cadastre endpoint&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ch.swisstopo-vd.stand-oerebkataster&lt;/code&gt;, field &lt;code&gt;oereb_webservice&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Point to property ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{service}/getegrid/json/?EN=e,n&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Property ID to full extract&lt;/td&gt;
&lt;td&gt;path varies by canton, call &lt;code&gt;capabilities/json/&lt;/code&gt; first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Building data, 79 fields&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ech/MapServer/ch.bfs.gebaeude_wohnungs_register/{featureId}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ground elevation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rest/services/height?easting=&amp;amp;northing=&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One shortcut worth knowing: the building register entry already contains the property identifier and the parcel number. For any address with a building on it, you can skip the cantonal call entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I still don't know
&lt;/h2&gt;

&lt;p&gt;All of the above is tested against one canton. There are 26, running at least two different implementations of the same specification, and I already know the paths differ between them. Mapping the rest is my next chore.&lt;/p&gt;

&lt;p&gt;If you've worked with the ÖREB service in another canton, I'd like to know which path shape yours uses. Leave it in the comments and I'll keep a running list in this post.&lt;/p&gt;

&lt;p&gt;And if your country has its own national open-data API with its own undocumented landmines, I'd read that. I'm starting to suspect they all have a coordinate-order problem somewhere.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I used an AI assistant to probe these endpoints with me and to clean up the draft. Every request and response in this post was actually run, and the outputs are copied from what came back.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>opendata</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
