[{"data":1,"prerenderedAt":8147},["ShallowReactive",2],{"blog-items":3},[4,194,294,414,547,879,1015,1298,1517,1650,1775,2600,2725,2861,3192,3325,3480,3860,3942,4025,4105,6187,6285,6438,6591,6687,6872,7007,7056,7128,7191,7275,7319,7403,7525,7555,7677,7830,7904,7989],{"id":5,"title":6,"abstract":7,"author":8,"body":13,"description":176,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":178,"meta":186,"modified":7,"navigation":187,"path":188,"proficiencyLevel":7,"published":189,"rawbody":190,"schemaOrg":7,"schemaType":7,"seo":191,"stem":192,"__hash__":193},"blog\u002Fblog\u002Fwhy-osm-routing-needs-real-time-traffic.md","Why Basic OpenStreetMap Routing Needs Real-Time Traffic",null,{"name":9,"jobTitle":10,"sameAs":11},"Ian Wagner","Founder & President \u002F COO",[12],"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fian-w-wagner\u002F",{"type":14,"value":15,"toc":167},"minimark",[16,20,27,32,48,52,55,84,87,91,106,127,131,140,143,151,154],[17,18,6],"h1",{"id":19},"why-basic-openstreetmap-routing-needs-real-time-traffic",[21,22,23],"blockquote",{},[24,25,26],"p",{},"OpenStreetMap (OSM) provides a world-class geographic foundation, but it remains a static dataset. Without real-time traffic integration, routing engines must rely on algorithmic proxies—like road class and legal speed limits—which often lead to unreliable ETAs and logistics bottlenecks.",[28,29,31],"h2",{"id":30},"the-problem","The Problem",[24,33,34,42,43,47],{},[35,36,41],"a",{"href":37,"rel":38,"target":40},"https:\u002F\u002Fwww.openstreetmap.org\u002Fabout",[39],"external","_blank","OpenStreetMap (OSM)"," is one of the world's leading road maps, but a persistent gap remains between fixed geographic data and a ",[35,44,46],{"href":45},"\u002Fproducts\u002Frouting-navigation\u002F","live navigation experience",". Without dedicated traffic data, Estimated Times of Arrival (ETAs) are essentially educated guesses. While OSM is excellent at mapping the world's road network, a static dataset cannot capture the actual driving conditions at this exact moment. In enterprise-grade logistics, the lack of live data is often the first significant technical hurdle.",[28,49,51],{"id":50},"the-limits-of-algorithmic-guesswork","The Limits of Algorithmic Guesswork",[24,53,54],{},"In the absence of real-time data, a routing engine must estimate travel speeds based on tags and a few common proxies:",[56,57,58,66,72,78],"ul",{},[59,60,61,65],"li",{},[62,63,64],"strong",{},"Road Class:"," Assuming a motorway is always faster than a residential street.",[59,67,68,71],{},[62,69,70],{},"Tagged Speed Limits:"," Using the legal maximum as the baseline (when the tag even exists).",[59,73,74,77],{},[62,75,76],{},"Network Density:"," Adjusting for urban vs. rural environments.",[59,79,80,83],{},[62,81,82],{},"Time of Day:"," Using low-granularity buckets like \"daytime\" and \"nighttime.\"",[24,85,86],{},"Real-world data show wild variances compared to these static estimates. Road class is a blunt instrument for predicting speed. Missing speed limit tags in open datasets force routing engines to rely on broad averages, resulting in unreliable ETAs and logistics delays. Rule-based algorithms are also notoriously bad at predicting choke points because open datasets don't account for traffic light timings, congestion near specific exits, or the \"invisible\" friction of a busy intersection.",[28,88,90],{"id":89},"the-stadia-maps-difference","The Stadia Maps Difference",[24,92,93,94,99,100,105],{},"To move from guesswork to precision, we integrated ",[35,95,98],{"href":96,"rel":97,"target":40},"https:\u002F\u002Fwww.tomtom.com\u002Fproducts\u002Ftraffic-apis\u002F",[39],"TomTom's global traffic data"," directly into the ",[35,101,104],{"href":102,"rel":103,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002F",[39],"Stadia Maps routing engine",". High-resolution historical profiles and live feeds allow for accurate, real-time routing. We provide this through three key technical pillars:",[107,108,109,115,121],"ol",{},[59,110,111,114],{},[62,112,113],{},"Global Coverage:"," Access to consistent data across more countries than almost any other vendor.",[59,116,117,120],{},[62,118,119],{},"Rapid Updates:"," A traffic latency of approximately two minutes allows our API to suggest alternate routes almost as soon as a wreck occurs.",[59,122,123,126],{},[62,124,125],{},"Historical Profiles:"," Deep granularity forms the backbone of predictive routing. High-resolution historical data enables accurate, time-dependent routing in advance, allowing you to plan a route for Tuesday at 8:00 AM based on what might happen on Tuesdays at 8:00 AM.",[28,128,130],{"id":129},"fleet-intelligence-at-scale","Fleet Intelligence at Scale",[24,132,133,134,139],{},"For dispatch, optimization, and fleet operations, ",[35,135,138],{"href":136,"rel":137,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Ftime-distance-matrix\u002F",[39],"matrix routing"," (calculating the time and distance between many origins and destinations) is the engine's most critical function.",[24,141,142],{},"The Stadia Maps infrastructure supports matrix requests that are significantly larger than most competitors allow on standard plans. By integrating traffic data directly into these large-scale requests, we eliminate the need for developers to split requests into smaller chunks, reducing unnecessary complexity and latency.",[24,144,145,146,150],{},"Developers maintain full agency over their implementation. We provide the fastest route based on live conditions, but the frequency of re-routing remains entirely in your control. Choice of revalidation frequency puts you in charge of the trade-off between real-time accuracy and ",[35,147,149],{"href":148},"\u002Fpricing\u002F","scaling costs",", ensuring your bills remain as predictable as your ETAs.",[152,153],"hr",{},[24,155,156,161,162,166],{},[35,157,160],{"href":158,"rel":159,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F",[39],"Create a free account"," to start building with real-time traffic and high-performance routing today. Our ",[35,163,165],{"href":102,"rel":164,"target":40},[39],"documentation"," provides everything you need to integrate TomTom-powered precision into your existing OSM workflow.",{"title":168,"searchDepth":169,"depth":169,"links":170},"",4,[171,173,174,175],{"id":30,"depth":172,"text":31},2,{"id":50,"depth":172,"text":51},{"id":89,"depth":172,"text":90},{"id":129,"depth":172,"text":130},"OpenStreetMap is a world-class road network, but without real-time traffic it's a static dataset. Here's why algorithmic ETAs fall apart in production logistics and how Stadia Maps closes the gap with TomTom-powered routing.","md",[179,180,181,182,183,184,185],"Routing","Navigation","OpenStreetMap","Traffic Data","Matrix Routing","Logistics","TomTom",{},true,"\u002Fblog\u002Fwhy-osm-routing-needs-real-time-traffic","2026-05-12","---\ndescription: >-\n  OpenStreetMap is a world-class road network, but without real-time traffic\n  it's a static dataset. Here's why algorithmic ETAs fall apart in production\n  logistics and how Stadia Maps closes the gap with TomTom-powered routing.\nexcerpt: >-\n  OpenStreetMap is great geography, but without real-time traffic it falls\n  short on ETAs. Stadia Maps closes the gap with TomTom-powered routing.\npublished: \"2026-05-12\"\nkeywords:\n  - Routing\n  - Navigation\n  - OpenStreetMap\n  - Traffic Data\n  - Matrix Routing\n  - Logistics\n  - TomTom\nauthor:\n  name: \"Ian Wagner\"\n  jobTitle: \"Founder & President \u002F COO\"\n  sameAs:\n    - \"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fian-w-wagner\u002F\"\n---\n\n# Why Basic OpenStreetMap Routing Needs Real-Time Traffic\n\n> OpenStreetMap (OSM) provides a world-class geographic foundation, but it remains a static dataset. Without real-time traffic integration, routing engines must rely on algorithmic proxies—like road class and legal speed limits—which often lead to unreliable ETAs and logistics bottlenecks.\n\n## The Problem\n\n[OpenStreetMap (OSM)](https:\u002F\u002Fwww.openstreetmap.org\u002Fabout) is one of the world's leading road maps, but a persistent gap remains between fixed geographic data and a [live navigation experience](\u002Fproducts\u002Frouting-navigation\u002F). Without dedicated traffic data, Estimated Times of Arrival (ETAs) are essentially educated guesses. While OSM is excellent at mapping the world's road network, a static dataset cannot capture the actual driving conditions at this exact moment. In enterprise-grade logistics, the lack of live data is often the first significant technical hurdle.\n\n## The Limits of Algorithmic Guesswork\n\nIn the absence of real-time data, a routing engine must estimate travel speeds based on tags and a few common proxies:\n\n- **Road Class:** Assuming a motorway is always faster than a residential street.\n- **Tagged Speed Limits:** Using the legal maximum as the baseline (when the tag even exists).\n- **Network Density:** Adjusting for urban vs. rural environments.\n- **Time of Day:** Using low-granularity buckets like \"daytime\" and \"nighttime.\"\n\nReal-world data show wild variances compared to these static estimates. Road class is a blunt instrument for predicting speed. Missing speed limit tags in open datasets force routing engines to rely on broad averages, resulting in unreliable ETAs and logistics delays. Rule-based algorithms are also notoriously bad at predicting choke points because open datasets don't account for traffic light timings, congestion near specific exits, or the \"invisible\" friction of a busy intersection.\n\n## The Stadia Maps Difference\n\nTo move from guesswork to precision, we integrated [TomTom's global traffic data](https:\u002F\u002Fwww.tomtom.com\u002Fproducts\u002Ftraffic-apis\u002F) directly into the [Stadia Maps routing engine](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002F). High-resolution historical profiles and live feeds allow for accurate, real-time routing. We provide this through three key technical pillars:\n\n1. **Global Coverage:** Access to consistent data across more countries than almost any other vendor.\n2. **Rapid Updates:** A traffic latency of approximately two minutes allows our API to suggest alternate routes almost as soon as a wreck occurs.\n3. **Historical Profiles:** Deep granularity forms the backbone of predictive routing. High-resolution historical data enables accurate, time-dependent routing in advance, allowing you to plan a route for Tuesday at 8:00 AM based on what might happen on Tuesdays at 8:00 AM.\n\n## Fleet Intelligence at Scale\n\nFor dispatch, optimization, and fleet operations, [matrix routing](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Ftime-distance-matrix\u002F) (calculating the time and distance between many origins and destinations) is the engine's most critical function.\n\nThe Stadia Maps infrastructure supports matrix requests that are significantly larger than most competitors allow on standard plans. By integrating traffic data directly into these large-scale requests, we eliminate the need for developers to split requests into smaller chunks, reducing unnecessary complexity and latency.\n\nDevelopers maintain full agency over their implementation. We provide the fastest route based on live conditions, but the frequency of re-routing remains entirely in your control. Choice of revalidation frequency puts you in charge of the trade-off between real-time accuracy and [scaling costs](\u002Fpricing\u002F), ensuring your bills remain as predictable as your ETAs.\n\n---\n\n[Create a free account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F) to start building with real-time traffic and high-performance routing today. Our [documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002F) provides everything you need to integrate TomTom-powered precision into your existing OSM workflow.\n",{"title":6,"description":176},"blog\u002Fwhy-osm-routing-needs-real-time-traffic","1_uB1rxO9vDr3MSN4MqjHJKIli8LrfMzzkPXHH5IhXc",{"id":195,"title":196,"abstract":7,"author":7,"body":197,"description":281,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":282,"meta":287,"modified":7,"navigation":187,"path":288,"proficiencyLevel":7,"published":289,"rawbody":290,"schemaOrg":7,"schemaType":7,"seo":291,"stem":292,"__hash__":293},"blog\u002Fblog\u002F2026-satellite-imagery-update.md","2026 Satellite Imagery Update: 37 Million km² at 30cm Resolution",{"type":14,"value":198,"toc":275},[199,202,205,214,224,228,231,234,238,241,244,253,257,260,263,267],[17,200,196],{"id":201},"_2026-satellite-imagery-update-37-million-km-at-30cm-resolution",[24,203,204],{},"If you've built anything on top of satellite imagery, you know the pain of inconsistent resolution. You zoom into one region and get crisp rooftops. Pan over to the next and it's a blurry patchwork from three years ago. That inconsistency isn't just cosmetic: it erodes trust in whatever you're building on top of it.",[24,206,207,208,213],{},"We regularly refresh our ",[35,209,212],{"href":210,"rel":211,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Fmaps\u002Fmap-styles\u002Fsatellite-imagery\u002F",[39],"Alidade Satellite"," imagery as new high-resolution data becomes available from Airbus. This update is one of our most significant, expanding both the depth and freshness of our coverage.",[215,216],"cross-platform-map",{":center":217,":scroll-zoom":218,":use-search":218,":use-theme-switcher":219,":zoom":220,"id":221,"style":222,"theme":223},"[139.6934,35.6857]","true","false","16.5","map","height: 400px;","alidade_satellite",[28,225,227],{"id":226},"_30cm-coverage-scaled","30cm Coverage, Scaled",[24,229,230],{},"We now offer 37 million km² of 30cm-resolution satellite imagery, enough detail to distinguish individual vehicles, building footprints, and infrastructure at high zoom levels. For applications like urban planning tools, insurance assessments, or logistics platforms, this is the difference between useful and decorative.",[24,232,233],{},"This release also adds seamless 30cm country-wide mosaics for Japan, Nigeria, Mexico, the UAE, and Eastern South Africa. \"Seamless\" matters here: no visible tile boundaries, no abrupt shifts in color or season. Just consistent, high-resolution coverage across the entire country.",[28,235,237],{"id":236},"a-fresher-global-baseline","A Fresher Global Baseline",[24,239,240],{},"Beyond the 30cm expansion, we've completed a full refresh of our 1.5m-resolution dataset covering the Earth's landmasses, derived from the latest SPOT Global layer. Even at lower zoom levels, you're working with current data rather than imagery that's aging out.",[24,242,243],{},"Freshness matters as much as resolution. Across our entire dataset, the area-weighted average age is roughly 1.6 years. Nearly two-thirds of our coverage is less than a year old, and only 7% is older than three years. That share continues to shrink with each refresh.",[24,245,246,247,252],{},"Combined with our ",[35,248,251],{"href":249,"rel":250,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fblog\u002F2025-satellite-imagery-refresh\u002F",[39],"2025 satellite imagery refresh",", every pixel in our dataset is still 1.5m or better, with 37 million km² at 30cm and another 7 million km² at 50cm.",[28,254,256],{"id":255},"what-this-means-for-your-stack","What This Means for Your Stack",[24,258,259],{},"If you're using Alidade Satellite, these updates are already live. No API changes, no migration. The same tile endpoints now serve fresher, sharper data. Integration works the same way it always has via MapLibre, Leaflet, OpenLayers, or any other mapping library that supports raster tiles.",[24,261,262],{},"We don't track or profile your end users. The imagery is delivered directly, with no behavioral tracking layer between your application and the tiles.",[28,264,266],{"id":265},"try-it","Try It",[24,268,269,270,274],{},"The updated satellite imagery is available now for all Stadia Maps customers. If you're new, ",[35,271,273],{"href":158,"rel":272,"target":40},[39],"create a free account"," and see the difference at zoom level 18.",{"title":168,"searchDepth":169,"depth":169,"links":276},[277,278,279,280],{"id":226,"depth":172,"text":227},{"id":236,"depth":172,"text":237},{"id":255,"depth":172,"text":256},{"id":265,"depth":172,"text":266},"The 2026 Alidade Satellite update expands 30cm-resolution coverage to 37 million km², adds seamless country-wide mosaics for Japan, Nigeria, Mexico, the UAE, and Eastern South Africa, and refreshes our global 1.5m baseline from the latest SPOT data.",[283,284,285,286,212],"Satellite Imagery","Aerial Photography","Map Update","High Resolution",{},"\u002Fblog\u002F2026-satellite-imagery-update","2026-04-27","---\ndescription: >-\n  The 2026 Alidade Satellite update expands 30cm-resolution coverage to 37 million km²,\n  adds seamless country-wide mosaics for Japan, Nigeria, Mexico, the UAE, and Eastern\n  South Africa, and refreshes our global 1.5m baseline from the latest SPOT data.\npublished: 2026-04-27\nkeywords:\n  - Satellite Imagery\n  - Aerial Photography\n  - Map Update\n  - High Resolution\n  - Alidade Satellite\n---\n\n# 2026 Satellite Imagery Update: 37 Million km² at 30cm Resolution\n\nIf you've built anything on top of satellite imagery, you know the pain of inconsistent resolution. You zoom into one region and get crisp rooftops. Pan over to the next and it's a blurry patchwork from three years ago. That inconsistency isn't just cosmetic: it erodes trust in whatever you're building on top of it.\n\nWe regularly refresh our [Alidade Satellite](https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Fmaps\u002Fmap-styles\u002Fsatellite-imagery\u002F) imagery as new high-resolution data becomes available from Airbus. This update is one of our most significant, expanding both the depth and freshness of our coverage.\n\n::cross-platform-map{id=\"map\" style=\"height: 400px;\"}\n---\ncenter: [139.6934, 35.6857]\nscroll-zoom: true\nzoom: 16.5\ntheme: alidade_satellite\nuse-theme-switcher: false\nuse-search: true\n---\n::\n\n## 30cm Coverage, Scaled\n\nWe now offer 37 million km² of 30cm-resolution satellite imagery, enough detail to distinguish individual vehicles, building footprints, and infrastructure at high zoom levels. For applications like urban planning tools, insurance assessments, or logistics platforms, this is the difference between useful and decorative.\n\nThis release also adds seamless 30cm country-wide mosaics for Japan, Nigeria, Mexico, the UAE, and Eastern South Africa. \"Seamless\" matters here: no visible tile boundaries, no abrupt shifts in color or season. Just consistent, high-resolution coverage across the entire country.\n\n## A Fresher Global Baseline\n\nBeyond the 30cm expansion, we've completed a full refresh of our 1.5m-resolution dataset covering the Earth's landmasses, derived from the latest SPOT Global layer. Even at lower zoom levels, you're working with current data rather than imagery that's aging out.\n\nFreshness matters as much as resolution. Across our entire dataset, the area-weighted average age is roughly 1.6 years. Nearly two-thirds of our coverage is less than a year old, and only 7% is older than three years. That share continues to shrink with each refresh.\n\nCombined with our [2025 satellite imagery refresh](https:\u002F\u002Fstadiamaps.com\u002Fblog\u002F2025-satellite-imagery-refresh\u002F), every pixel in our dataset is still 1.5m or better, with 37 million km² at 30cm and another 7 million km² at 50cm.\n\n## What This Means for Your Stack\n\nIf you're using Alidade Satellite, these updates are already live. No API changes, no migration. The same tile endpoints now serve fresher, sharper data. Integration works the same way it always has via MapLibre, Leaflet, OpenLayers, or any other mapping library that supports raster tiles.\n\nWe don't track or profile your end users. The imagery is delivered directly, with no behavioral tracking layer between your application and the tiles.\n\n## Try It\n\nThe updated satellite imagery is available now for all Stadia Maps customers. If you're new, [create a free account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F) and see the difference at zoom level 18.\n",{"title":196,"description":281},"blog\u002F2026-satellite-imagery-update","rXkN7g9kogazJmkef_JKypDkZmhjCF0bsZzwTAdv4TM",{"id":295,"title":296,"abstract":7,"author":7,"body":297,"description":400,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":401,"meta":408,"modified":7,"navigation":187,"path":409,"proficiencyLevel":7,"published":289,"rawbody":410,"schemaOrg":7,"schemaType":7,"seo":411,"stem":412,"__hash__":413},"blog\u002Fblog\u002F75-million-more-addresses-geocoding-precision.md","75 Million More Addresses: Expanding Geocoding Precision",{"type":14,"value":298,"toc":392},[299,302,305,308,312,315,318,322,325,329,338,341,345,361,364,371,375,378,381,385],[17,300,296],{"id":301},"_75-million-more-addresses-expanding-geocoding-precision",[24,303,304],{},"Inaccurate geocoding breaks the user experience. If your query returns a street-level guess instead of a rooftop coordinate, a user might be on the right street but the wrong block, or a delivery driver gets routed to an approximate centroid instead of a front door. The coordinates are \"close enough\" until they aren't, and your application takes the blame.",[24,306,307],{},"We continuously update our geocoding dataset as new address and POI data becomes available. This release is our largest expansion yet: 75 million new addresses, 3 million new points of interest, improved intent recognition, and a new way to query with structured address fields.",[28,309,311],{"id":310},"rooftop-level-accuracy-at-scale","Rooftop-Level Accuracy at Scale",[24,313,314],{},"The bulk of this expansion comes from OpenAddresses, one of the largest open datasets of address-level coordinates. These aren't interpolated guesses along a road segment. They're rooftop-level points tied to individual parcels, which matters for any application that depends on precise placement: routing, last-mile logistics, property lookup.",[24,316,317],{},"The gains aren't spread evenly. France and the US lead with roughly 25 million new addresses each, followed by Germany with 3 million and notable expansions across Brazil, Australia, and Mexico. If you've been hitting street-level fallbacks in these regions, you should see noticeably better results.",[28,319,321],{"id":320},"fresher-points-of-interest","Fresher Points of Interest",[24,323,324],{},"POI data goes stale quickly. A restaurant opens, a shop closes, a business moves across the street, and suddenly your search results are sending users to the wrong place. We've added 3 million POIs from Foursquare OS Places, bringing our dataset more in line with what's actually on the ground. Better coverage for the kinds of searches your users actually run: finding a specific restaurant, locating the nearest pharmacy, or navigating to a business that opened last month.",[28,326,328],{"id":327},"smarter-search-fewer-misses","Smarter Search, Fewer Misses",[24,330,331,332,337],{},"Beyond raw data, we've improved how our ",[35,333,336],{"href":334,"rel":335,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Fgeocoding-search\u002Fgeocoding\u002F",[39],"\u002Fsearch APIs"," interpret what users actually mean. The changes focus on intent recognition: better handling of queries for larger geographic areas, complex or compound place names, and cases where the most obvious textual match isn't the right result.",[24,339,340],{},"Your users should find more of what they're looking for on the first try.",[28,342,344],{"id":343},"structured-address-input-now-on-v1","Structured Address Input, Now on v1",[24,346,347,348,352,353,356,357,360],{},"For developers working with structured address data, this release adds ",[349,350,351],"code",{},"house_number",", ",[349,354,355],{},"street",", and ",[349,358,359],{},"unit"," as first-class fields on the geocoding API. Previously, structured queries supported country, region, and postal code, but the address itself arrived as a single text field that we had to parse before running a match.",[24,362,363],{},"If your dataset is already structured that way, you can now pass it through directly. This is common for shipping, CRM, and property data. Queries with the new fields skip the parsing step entirely, which typically means better match quality and faster responses.",[24,365,366,367,370],{},"The free-text ",[349,368,369],{},"address"," field isn't going anywhere. If you only have a single string, we'll still parse it for you. The new fields are available on v1 today. Adopt them at your own pace.",[28,372,374],{"id":373},"no-tracking-required","No Tracking Required",[24,376,377],{},"A common assumption in the industry is that better geocoding requires more user data: search history, device location, behavioral signals. We don't work that way. These improvements come from better source data and smarter algorithms, not from profiling your end users. Your users' queries are yours, not ours.",[24,379,380],{},"As with everything we build, these updates are available through standard APIs and SDKs, including MapLibre and Leaflet. Technical precision, fair pricing, and privacy are baked in from the start.",[28,382,384],{"id":383},"get-started","Get Started",[24,386,387,388,391],{},"The expanded dataset, structured address fields, and search improvements are live now for all Stadia Maps customers. New here? ",[35,389,160],{"href":158,"rel":390,"target":40},[39]," and start geocoding.",{"title":168,"searchDepth":169,"depth":169,"links":393},[394,395,396,397,398,399],{"id":310,"depth":172,"text":311},{"id":320,"depth":172,"text":321},{"id":327,"depth":172,"text":328},{"id":343,"depth":172,"text":344},{"id":373,"depth":172,"text":374},{"id":383,"depth":172,"text":384},"Our largest geocoding dataset expansion yet: 75 million new addresses from OpenAddresses, 3 million new POIs from Foursquare OS Places, smarter intent recognition, and new structured address fields (house_number, street, unit) on the v1 search API.",[402,403,404,405,406,407],"Geocoding","Addresses","OpenAddresses","Foursquare OS Places","Structured Search","Points of Interest",{},"\u002Fblog\u002F75-million-more-addresses-geocoding-precision","---\ndescription: >-\n  Our largest geocoding dataset expansion yet: 75 million new addresses from OpenAddresses,\n  3 million new POIs from Foursquare OS Places, smarter intent recognition, and new\n  structured address fields (house_number, street, unit) on the v1 search API.\npublished: 2026-04-27\nkeywords:\n  - Geocoding\n  - Addresses\n  - OpenAddresses\n  - Foursquare OS Places\n  - Structured Search\n  - Points of Interest\n---\n\n# 75 Million More Addresses: Expanding Geocoding Precision\n\nInaccurate geocoding breaks the user experience. If your query returns a street-level guess instead of a rooftop coordinate, a user might be on the right street but the wrong block, or a delivery driver gets routed to an approximate centroid instead of a front door. The coordinates are \"close enough\" until they aren't, and your application takes the blame.\n\nWe continuously update our geocoding dataset as new address and POI data becomes available. This release is our largest expansion yet: 75 million new addresses, 3 million new points of interest, improved intent recognition, and a new way to query with structured address fields.\n\n## Rooftop-Level Accuracy at Scale\n\nThe bulk of this expansion comes from OpenAddresses, one of the largest open datasets of address-level coordinates. These aren't interpolated guesses along a road segment. They're rooftop-level points tied to individual parcels, which matters for any application that depends on precise placement: routing, last-mile logistics, property lookup.\n\nThe gains aren't spread evenly. France and the US lead with roughly 25 million new addresses each, followed by Germany with 3 million and notable expansions across Brazil, Australia, and Mexico. If you've been hitting street-level fallbacks in these regions, you should see noticeably better results.\n\n## Fresher Points of Interest\n\nPOI data goes stale quickly. A restaurant opens, a shop closes, a business moves across the street, and suddenly your search results are sending users to the wrong place. We've added 3 million POIs from Foursquare OS Places, bringing our dataset more in line with what's actually on the ground. Better coverage for the kinds of searches your users actually run: finding a specific restaurant, locating the nearest pharmacy, or navigating to a business that opened last month.\n\n## Smarter Search, Fewer Misses\n\nBeyond raw data, we've improved how our [\u002Fsearch APIs](https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Fgeocoding-search\u002Fgeocoding\u002F) interpret what users actually mean. The changes focus on intent recognition: better handling of queries for larger geographic areas, complex or compound place names, and cases where the most obvious textual match isn't the right result.\n\nYour users should find more of what they're looking for on the first try.\n\n## Structured Address Input, Now on v1\n\nFor developers working with structured address data, this release adds `house_number`, `street`, and `unit` as first-class fields on the geocoding API. Previously, structured queries supported country, region, and postal code, but the address itself arrived as a single text field that we had to parse before running a match.\n\nIf your dataset is already structured that way, you can now pass it through directly. This is common for shipping, CRM, and property data. Queries with the new fields skip the parsing step entirely, which typically means better match quality and faster responses.\n\nThe free-text `address` field isn't going anywhere. If you only have a single string, we'll still parse it for you. The new fields are available on v1 today. Adopt them at your own pace.\n\n## No Tracking Required\n\nA common assumption in the industry is that better geocoding requires more user data: search history, device location, behavioral signals. We don't work that way. These improvements come from better source data and smarter algorithms, not from profiling your end users. Your users' queries are yours, not ours.\n\nAs with everything we build, these updates are available through standard APIs and SDKs, including MapLibre and Leaflet. Technical precision, fair pricing, and privacy are baked in from the start.\n\n## Get Started\n\nThe expanded dataset, structured address fields, and search improvements are live now for all Stadia Maps customers. New here? [Create a free account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F) and start geocoding.\n",{"title":296,"description":400},"blog\u002F75-million-more-addresses-geocoding-precision","j4DO9yePU2yMf7Dmk2iG0zU7zur5kHKvfYLqCkcT14Y",{"id":415,"title":416,"abstract":7,"author":7,"body":417,"description":532,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":533,"meta":540,"modified":7,"navigation":187,"path":541,"proficiencyLevel":7,"published":542,"rawbody":543,"schemaOrg":7,"schemaType":7,"seo":544,"stem":545,"__hash__":546},"blog\u002Fblog\u002Ftraffic-influenced-routing-in-public-preview.md","Traffic-Influenced Routing Is Here (Public Preview)",{"type":14,"value":418,"toc":527},[419,422,425,429,459,462,476,479,483,486,488,491,519],[17,420,416],{"id":421},"traffic-influenced-routing-is-here-public-preview",[24,423,424],{},"Routing without traffic data works for a lot of use cases.\nBut dispatch systems need ETAs that account for rush hour,\nride-hailing platforms need accurate pickup times,\nand telematics pipelines need traffic context to reconstruct accurate travel times.\nFor these use cases,\nrouting and ETAs that only reflect the road network,\nwithout accounting for what's happening on it,\nfall short.",[28,426,428],{"id":427},"available-today","Available Today",[24,430,431,432,437,438,437,443,437,448,453,454,458],{},"Starting today,\nStadia Maps customers on Standard and Professional plans can use traffic-influenced routing,\na public preview that brings live and historical traffic data into route calculations across\n",[35,433,436],{"href":434,"rel":435,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fstandard-routing\u002F",[39],"standard routing",",\n",[35,439,442],{"href":440,"rel":441,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Foptimized-routing\u002F",[39],"optimized routing",[35,444,447],{"href":445,"rel":446,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fmap-matching\u002F",[39],"map matching",[35,449,452],{"href":450,"rel":451,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fisochrones\u002F",[39],"isochrones",",\nand ",[35,455,457],{"href":136,"rel":456,"target":40},[39],"time\u002Fdistance matrices",".",[24,460,461],{},"The traffic data comes from TomTom and covers 80+ countries at launch,\nlayered onto the same OSM-based road network you already use.\nYou get two tiers to choose from,\nand you can pick per request,\nso you can use both in the same app:",[56,463,464,470],{},[59,465,466,469],{},[62,467,468],{},"Adaptive"," balances accuracy and credit cost.\nA good fit for general routing, isochrones, and map matching.",[59,471,472,475],{},[62,473,474],{},"Premium"," combines real-time conditions with predictive data for the highest accuracy.\nIdeal where precise ETAs matter,\nlike live fleet routing and matrix requests.",[24,477,478],{},"Both tiers work across auto, bus, taxi, and truck profiles.\nAnd because this is Stadia Maps,\nyou can still tune all the same profile parameters you're used to.\nTraffic-influenced routing builds on the full Stadia Maps routing stack you already know:\nnot a locked-down replacement,\nand without the proprietary detour.",[28,480,482],{"id":481},"pricing-that-scales-with-you-not-against-you","Pricing That Scales With You, Not Against You",[24,484,485],{},"We built this the way we build everything:\nwith fair, transparent pricing and no gotchas.\nYou pick the routing profile and traffic tier per request,\nuse your existing credits with no surprise minimums,\nand upgrade with a single profile parameter change.\nYou can finally use traffic-influenced routing with no contract renegotiation,\nno new SDK,\nand no mandatory user tracking;\nyour users' privacy is still the default.",[28,487,384],{"id":383},[24,489,490],{},"Traffic-influenced routing is available now in public preview.",[56,492,493,502,511],{},[59,494,495,496,501],{},"See the ",[35,497,500],{"href":498,"rel":499,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Frouting-navigation\u002Ftraffic-influenced-routing\u002F",[39],"Product page"," for an overview",[59,503,504,505,510],{},"Read the ",[35,506,509],{"href":507,"rel":508,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fstandard-routing\u002F#traffic-influenced-profiles",[39],"Routing docs"," for profile details",[59,512,513,514],{},"Get started with the ",[35,515,518],{"href":516,"rel":517,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fguides\u002Fgetting-the-best-routes-with-valhalla-turn-by-turn-directions-apis\u002F#traffic-influenced-routing",[39],"Integration guide",[24,520,521,522,526],{},"Already on a Standard or Professional plan?\nYou can start using it right now.\nOn a different plan?\n",[35,523,525],{"href":524},"mailto:support@stadiamaps.com?subject=Traffic-Influenced%20Routing%20Trial","Reach out"," and we can set you up with a trial.",{"title":168,"searchDepth":169,"depth":169,"links":528},[529,530,531],{"id":427,"depth":172,"text":428},{"id":481,"depth":172,"text":482},{"id":383,"depth":172,"text":384},"Traffic-influenced routing is now available in public preview, bringing live and historical traffic data to standard routing, optimized routing, map matching, isochrones, and time\u002Fdistance matrices.",[534,535,536,537,538,539],"Traffic-Influenced Routing","Real-Time Traffic","Route Optimization","Fleet Routing","ETA Accuracy","Public Preview",{},"\u002Fblog\u002Ftraffic-influenced-routing-in-public-preview","2026-04-14","---\ndescription: >-\n  Traffic-influenced routing is now available in public preview,\n  bringing live and historical traffic data to standard routing,\n  optimized routing, map matching, isochrones, and time\u002Fdistance matrices.\npublished: 2026-04-14\nkeywords:\n  - Traffic-Influenced Routing\n  - Real-Time Traffic\n  - Route Optimization\n  - Fleet Routing\n  - ETA Accuracy\n  - Public Preview\n---\n\n# Traffic-Influenced Routing Is Here (Public Preview)\n\nRouting without traffic data works for a lot of use cases.\nBut dispatch systems need ETAs that account for rush hour,\nride-hailing platforms need accurate pickup times,\nand telematics pipelines need traffic context to reconstruct accurate travel times.\nFor these use cases, \nrouting and ETAs that only reflect the road network,\nwithout accounting for what's happening on it,\nfall short.\n\n## Available Today\n\nStarting today,\nStadia Maps customers on Standard and Professional plans can use traffic-influenced routing,\na public preview that brings live and historical traffic data into route calculations across\n[standard routing](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fstandard-routing\u002F),\n[optimized routing](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Foptimized-routing\u002F),\n[map matching](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fmap-matching\u002F),\n[isochrones](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fisochrones\u002F),\nand [time\u002Fdistance matrices](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Ftime-distance-matrix\u002F).\n\nThe traffic data comes from TomTom and covers 80+ countries at launch,\nlayered onto the same OSM-based road network you already use.\nYou get two tiers to choose from,\nand you can pick per request,\nso you can use both in the same app:\n\n- **Adaptive** balances accuracy and credit cost.\n  A good fit for general routing, isochrones, and map matching.\n- **Premium** combines real-time conditions with predictive data for the highest accuracy.\n  Ideal where precise ETAs matter,\n  like live fleet routing and matrix requests.\n\nBoth tiers work across auto, bus, taxi, and truck profiles.\nAnd because this is Stadia Maps,\nyou can still tune all the same profile parameters you're used to.\nTraffic-influenced routing builds on the full Stadia Maps routing stack you already know:\nnot a locked-down replacement,\nand without the proprietary detour.\n\n## Pricing That Scales With You, Not Against You\n\nWe built this the way we build everything:\nwith fair, transparent pricing and no gotchas.\nYou pick the routing profile and traffic tier per request,\nuse your existing credits with no surprise minimums,\nand upgrade with a single profile parameter change.\nYou can finally use traffic-influenced routing with no contract renegotiation,\nno new SDK,\nand no mandatory user tracking;\nyour users' privacy is still the default.\n\n## Get Started\n\nTraffic-influenced routing is available now in public preview.\n \n- See the [Product page](https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Frouting-navigation\u002Ftraffic-influenced-routing\u002F) for an overview\n- Read the [Routing docs](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fstandard-routing\u002F#traffic-influenced-profiles) for profile details\n- Get started with the [Integration guide](https:\u002F\u002Fdocs.stadiamaps.com\u002Fguides\u002Fgetting-the-best-routes-with-valhalla-turn-by-turn-directions-apis\u002F#traffic-influenced-routing)\n \nAlready on a Standard or Professional plan?\nYou can start using it right now.\nOn a different plan?\n[Reach out](mailto:support@stadiamaps.com?subject=Traffic-Influenced%20Routing%20Trial) and we can set you up with a trial.",{"title":416,"description":532},"blog\u002Ftraffic-influenced-routing-in-public-preview","8lqNk71y8ioiK4madSH5qMHhMAS2FyPN7Bwbyg7B1pA",{"id":548,"title":549,"abstract":7,"author":7,"body":550,"description":862,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":863,"meta":870,"modified":7,"navigation":187,"path":871,"proficiencyLevel":872,"published":873,"rawbody":874,"schemaOrg":7,"schemaType":875,"seo":876,"stem":877,"__hash__":878},"blog\u002Fblog\u002Fai-tools-for-api-companies-ai-native-design-principles.md","AI Tools for API Companies: 4 Design Principles for AI-Native API Consumption",{"type":14,"value":551,"toc":855},[552,555,563,566,569,573,576,584,589,592,595,600,603,607,615,618,621,625,628,635,696,699,702,782,785,789,792,800,803,810,813,817,824,827,830,833,836,851],[17,553,549],{"id":554},"ai-tools-for-api-companies-4-design-principles-for-ai-native-api-consumption",[24,556,557,558,562],{},"In our ",[35,559,561],{"href":560},"\u002Fblog\u002Fai-tools-for-api-companies-ai-needs-context\u002F","previous article",",\nwe shared how our \"obvious\" approach to building tools for AI—auto-generating a MCP server from existing documentation and OpenAPI specs—failed spectacularly.\nAfter that failure, we had to learn how to design tools specifically for AI consumption.",[24,564,565],{},"We observed a fundamental difference between human developers and AI models:\nAI models have no persistent memory across sessions.\nWhen a human first encounters your API, they might struggle with the options, but after a few uses,\nthey internalize what works best.\nAI models don't.\nEvery conversation is their first time using your API.\nFor example, a breakthrough understanding about when to use country filters versus bounding boxes is lost the moment the chat ends.\nThis fundamental limitation drives every design decision that follows.",[24,567,568],{},"In the process of overhauling our MCP server,\nwe developed four guiding principles to help build the best tools for AI as an API company.",[28,570,572],{"id":571},"tool-descriptions-are-critical","Tool Descriptions Are Critical",[24,574,575],{},"We learned that tool descriptions do the heavy lifting.\nThe description is your chance to tell the model not just what your tool does,\nbut when and why a model might want to use it.\nA good description helps the model choose the right tool for the job and understand the context where it's most useful.",[24,577,578,579,583],{},"Our ",[35,580,582],{"href":581},"\u002Fproducts\u002Fmaps\u002Fstatic-maps\u002F","Static Maps API"," demonstrates this well. Originally, we described it as:",[21,585,586],{},[24,587,588],{},"Generate a map with a marker at a specific location. Returns a PNG image.",[24,590,591],{},"This description was technically accurate but too narrow.\nModels would only use it when explicitly asked for \"a map with a marker,\"\nmissing opportunities where it could create useful visualizations.",[24,593,594],{},"Now we describe it as:",[21,596,597],{},[24,598,599],{},"Generate a PNG map image of an area, optionally including markers and a line (e.g. to draw a route or a boundary)",[24,601,602],{},"The improved description helps models understand the broader capabilities and context where the tool is useful.\nInstead of only thinking \"marker on map,\" they now consider it for routes, boundaries, and general area visualization.",[28,604,606],{"id":605},"context-window-management-matters","Context Window Management Matters",[24,608,609,610,614],{},"We discovered that token consumption is a hidden constraint.\nLarge tool descriptions and verbose responses quickly eat into the available,\nor perhaps more importantly, ",[611,612,613],"em",{},"usable"," context window, leaving less room for user input and driving up costs.",[24,616,617],{},"The cost of cognitive load taught us to be frugal with our tool descriptions and the number of parameters for each tool.\nEvery word needed to help the model understand when to use the tool or how to interpret the results.\nThe same applies to tool responses.\nInstead of packing responses with potentially useful but unnecessary elements,\neach element of the response should be focused on helping the model answer the question.",[24,619,620],{},"We believe this merits further investigation.\nWe want to understand how tuning descriptions for specific models could yield even better performance,\nespecially different AI models interpret tool descriptions in different ways.",[28,622,624],{"id":623},"optimize-output-formats-for-ai-interpretation","Optimize Output Formats for AI Interpretation",[24,626,627],{},"Our API responses, while great for programmatic consumption, needed rethinking for AI consumption.\nInstead of just returning raw JSON, we started designing responses that help models interpret and use the data effectively.\nSometimes this meant adding human-readable summaries alongside or instead of structured data.\nOther times it meant restructuring the response to highlight the most relevant information.\nThe goal was always to reduce the cognitive load on the model while preserving the essential information.",[24,629,578,630,634],{},[35,631,633],{"href":632},"\u002Fproducts\u002Fgeospatial-apis\u002F","Timezone API"," illustrates this perfectly.\nOriginally, we returned the technical data that developers needed:",[636,637,641],"pre",{"className":638,"code":639,"language":640,"meta":168,"style":168},"language-json shiki shiki-themes github-light","{\n  \"tz_id\": \"Europe\u002FZurich\",\n  \"base_utc_offset\": 3600,\n  \"dst_offset\": 3600\n}\n","json",[349,642,643,652,667,680,690],{"__ignoreMap":168},[644,645,648],"span",{"class":646,"line":647},"line",1,[644,649,651],{"class":650},"sgsFI","{\n",[644,653,654,658,661,665],{"class":646,"line":172},[644,655,657],{"class":656},"sYu0t","  \"tz_id\"",[644,659,660],{"class":650},": ",[644,662,664],{"class":663},"sYBdl","\"Europe\u002FZurich\"",[644,666,437],{"class":650},[644,668,670,673,675,678],{"class":646,"line":669},3,[644,671,672],{"class":656},"  \"base_utc_offset\"",[644,674,660],{"class":650},[644,676,677],{"class":656},"3600",[644,679,437],{"class":650},[644,681,682,685,687],{"class":646,"line":169},[644,683,684],{"class":656},"  \"dst_offset\"",[644,686,660],{"class":650},[644,688,689],{"class":656},"3600\n",[644,691,693],{"class":646,"line":692},5,[644,694,695],{"class":650},"}\n",[24,697,698],{},"This worked fine for developers who could calculate the current local time themselves.\nBut AI models struggled with a surprising limitation: they don't inherently know what time it is right now.\nWhen someone asked \"Is this restaurant in Zurich open now?\",\nmodels couldn't reliably determine the current local time from just the timezone offset data.",[24,700,701],{},"So we added the local timestamps to our response:",[636,703,705],{"className":638,"code":704,"language":640,"meta":168,"style":168},"{\n  \"tz_id\": \"Europe\u002FZurich\",\n  \"base_utc_offset\": 3600,\n  \"dst_offset\": 3600,\n  \"timestamp\": 1749479378,\n  \"local_rfc_2822_timestamp\": \"Mon, 9 Jun 2025 16:29:38 +0200\",\n  \"local_rfc_3389_timestamp\": \"2025-06-09T16:29:38+02:00\"\n}\n",[349,706,707,711,721,731,741,753,766,777],{"__ignoreMap":168},[644,708,709],{"class":646,"line":647},[644,710,651],{"class":650},[644,712,713,715,717,719],{"class":646,"line":172},[644,714,657],{"class":656},[644,716,660],{"class":650},[644,718,664],{"class":663},[644,720,437],{"class":650},[644,722,723,725,727,729],{"class":646,"line":669},[644,724,672],{"class":656},[644,726,660],{"class":650},[644,728,677],{"class":656},[644,730,437],{"class":650},[644,732,733,735,737,739],{"class":646,"line":169},[644,734,684],{"class":656},[644,736,660],{"class":650},[644,738,677],{"class":656},[644,740,437],{"class":650},[644,742,743,746,748,751],{"class":646,"line":692},[644,744,745],{"class":656},"  \"timestamp\"",[644,747,660],{"class":650},[644,749,750],{"class":656},"1749479378",[644,752,437],{"class":650},[644,754,756,759,761,764],{"class":646,"line":755},6,[644,757,758],{"class":656},"  \"local_rfc_2822_timestamp\"",[644,760,660],{"class":650},[644,762,763],{"class":663},"\"Mon, 9 Jun 2025 16:29:38 +0200\"",[644,765,437],{"class":650},[644,767,769,772,774],{"class":646,"line":768},7,[644,770,771],{"class":656},"  \"local_rfc_3389_timestamp\"",[644,773,660],{"class":650},[644,775,776],{"class":663},"\"2025-06-09T16:29:38+02:00\"\n",[644,778,780],{"class":646,"line":779},8,[644,781,695],{"class":650},[24,783,784],{},"Now AI models can immediately understand both the current local time and work with the format they parse most naturally.\nThis change also made the API more useful for human developers who previously had to calculate local time themselves.",[28,786,788],{"id":787},"split-complex-endpoints-into-focused-tools","Split Complex Endpoints into Focused Tools",[24,790,791],{},"Our biggest breakthrough came from abandoning the one-tool-per-endpoint approach.\nInstead of exposing our every endpoint as a tool with many parameters,\nwe learned to split them into focused, use-case-specific tools,\noften removing complexity to ensure models can effectively use each tool.",[24,793,794,795,799],{},"Take our ",[35,796,798],{"href":797},"\u002Fproducts\u002Fgeocoding-search\u002Fgeocoding\u002F","geocoding"," tool as an example.\nOriginally, we exposed all the filtering options available in our API—bounding box coordinates,\ncircular search areas, layer filters, and country restrictions.\nWe thought giving AI models more control would lead to better results.",[24,801,802],{},"In practice, the models never used most of these options, even when they should have.\nWhen they did try to use them, they often got confused about which filter was most appropriate and picked sub-optimal choices.\nA request to \"find coffee shops in downtown Seoul\" might trigger attempts to calculate bounding box coordinates rather than simply using the country filter.",[24,804,805,806,809],{},"We eventually eliminated everything except the country filter.\nWe kept this one because it was the simplest—just a 3-character ISO code rather than coordinate lists for bounding boxes or radius calculations.\nIt also happens that most models can figure out country codes quite easily from their pre-trained general knowledge,\nturning \"find addresses in South Korea\" into a simple ",[349,807,808],{},"country: \"KOR\""," parameter.",[24,811,812],{},"The key insight: AI models perform better with multiple simple tools than one complex tool.\nThey can chain together focused tools to solve complex problems,\nbut they struggle to navigate a tool with dozens of configuration options.\nAs our tool usage grows, we expect to iteratively add new,\nfocused tools based on our existing endpoints to better help models answer location questions.",[28,814,816],{"id":815},"from-spectacular-failure-to-working-tools","From Spectacular Failure to Working Tools",[24,818,819,820,823],{},"These four principles transformed our MCP server:\ncontextual tool descriptions, focused endpoint splitting,\nAI-optimized responses, and careful token management.\nAs we discovered them, the spectacular failure we described in our ",[35,821,822],{"href":560},"first article"," became something that actually works.\nAI models can now successfully help users find routes, geocode addresses, and interact with our location services in natural, intuitive ways.",[24,825,826],{},"But mastering the technical aspects of tool design was just the beginning.\nThe real surprises came from what we learned about our own APIs in the process,\nand the unexpected capabilities that emerged when AI agents started orchestrating our tools in ways we'd never anticipated.",[24,828,829],{},"These insights go far beyond tool design and touch on fundamental questions about how API companies should think about AI-native development,\ndeveloper experience, and business strategy in an agent-driven world.",[24,831,832],{},"In our next article,\nwe'll explore how building our MCP server became a mirror that revealed opportunities to improve our underlying APIs,\nand how it unlocked user workflows we never had to build ourselves.\nThe technical lessons covered here are essential,\nbut they're just the foundation for understanding what AI-native API consumption really means.",[24,834,835],{},"For now, if you're building your own tools for AI,\nstart with these principles and prepare to be surprised by what you learn about your own APIs in the process.",[24,837,838,839,844,845,850],{},"Want to see these principles in action?\nCheck out our ",[35,840,843],{"href":841,"rel":842,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-mcp-server-ts",[39],"MCP Server on GitHub"," and join our ",[35,846,849],{"href":847,"rel":848,"target":40},"https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT",[39],"Discord"," to discuss your own experiences with other developers tackling these same challenges.",[852,853,854],"style",{},"html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":168,"searchDepth":169,"depth":169,"links":856},[857,858,859,860,861],{"id":571,"depth":172,"text":572},{"id":605,"depth":172,"text":606},{"id":623,"depth":172,"text":624},{"id":787,"depth":172,"text":788},{"id":815,"depth":172,"text":816},"The four design principles we discovered for building tools for AI that models actually use and understand. This is the second post in our series about AI tools for API companies.",[864,865,866,867,868,869],"AI","MCP","Model Context Protocol","API Design","AI Agents","Tool Design",{},"\u002Fblog\u002Fai-tools-for-api-companies-ai-native-design-principles","Expert","2025-08-07","---\ndescription: >-\n  The four design principles we discovered for building tools for AI that models actually use and understand.\n  This is the second post in our series about AI tools for API companies.\npublished: \"2025-08-07\"\nkeywords:\n  - AI\n  - MCP\n  - Model Context Protocol\n  - API Design\n  - AI Agents\n  - Tool Design\nschemaType: TechArticle\nproficiencyLevel: Expert\n---\n\n# AI Tools for API Companies: 4 Design Principles for AI-Native API Consumption\n\nIn our [previous article](\u002Fblog\u002Fai-tools-for-api-companies-ai-needs-context\u002F), \nwe shared how our \"obvious\" approach to building tools for AI—auto-generating a MCP server from existing documentation and OpenAPI specs—failed spectacularly. \nAfter that failure, we had to learn how to design tools specifically for AI consumption.\n\nWe observed a fundamental difference between human developers and AI models: \nAI models have no persistent memory across sessions. \nWhen a human first encounters your API, they might struggle with the options, but after a few uses, \nthey internalize what works best. \nAI models don't. \nEvery conversation is their first time using your API.\nFor example, a breakthrough understanding about when to use country filters versus bounding boxes is lost the moment the chat ends. \nThis fundamental limitation drives every design decision that follows.\n\nIn the process of overhauling our MCP server, \nwe developed four guiding principles to help build the best tools for AI as an API company.\n\n## Tool Descriptions Are Critical\n\nWe learned that tool descriptions do the heavy lifting.\nThe description is your chance to tell the model not just what your tool does, \nbut when and why a model might want to use it. \nA good description helps the model choose the right tool for the job and understand the context where it's most useful.\n\nOur [Static Maps API](\u002Fproducts\u002Fmaps\u002Fstatic-maps\u002F) demonstrates this well. Originally, we described it as:\n\n> Generate a map with a marker at a specific location. Returns a PNG image.\n\nThis description was technically accurate but too narrow.\nModels would only use it when explicitly asked for \"a map with a marker,\" \nmissing opportunities where it could create useful visualizations.\n\nNow we describe it as:\n\n> Generate a PNG map image of an area, optionally including markers and a line (e.g. to draw a route or a boundary)\n\nThe improved description helps models understand the broader capabilities and context where the tool is useful. \nInstead of only thinking \"marker on map,\" they now consider it for routes, boundaries, and general area visualization.\n\n## Context Window Management Matters\n\nWe discovered that token consumption is a hidden constraint. \nLarge tool descriptions and verbose responses quickly eat into the available, \nor perhaps more importantly, *usable* context window, leaving less room for user input and driving up costs.\n\nThe cost of cognitive load taught us to be frugal with our tool descriptions and the number of parameters for each tool. \nEvery word needed to help the model understand when to use the tool or how to interpret the results. \nThe same applies to tool responses. \nInstead of packing responses with potentially useful but unnecessary elements, \neach element of the response should be focused on helping the model answer the question.\n\nWe believe this merits further investigation.\nWe want to understand how tuning descriptions for specific models could yield even better performance, \nespecially different AI models interpret tool descriptions in different ways.\n\n## Optimize Output Formats for AI Interpretation\n\nOur API responses, while great for programmatic consumption, needed rethinking for AI consumption. \nInstead of just returning raw JSON, we started designing responses that help models interpret and use the data effectively. \nSometimes this meant adding human-readable summaries alongside or instead of structured data. \nOther times it meant restructuring the response to highlight the most relevant information. \nThe goal was always to reduce the cognitive load on the model while preserving the essential information.\n\nOur [Timezone API](\u002Fproducts\u002Fgeospatial-apis\u002F) illustrates this perfectly. \nOriginally, we returned the technical data that developers needed:\n\n```json\n{\n  \"tz_id\": \"Europe\u002FZurich\",\n  \"base_utc_offset\": 3600,\n  \"dst_offset\": 3600\n}\n```\n\nThis worked fine for developers who could calculate the current local time themselves. \nBut AI models struggled with a surprising limitation: they don't inherently know what time it is right now. \nWhen someone asked \"Is this restaurant in Zurich open now?\", \nmodels couldn't reliably determine the current local time from just the timezone offset data.\n\nSo we added the local timestamps to our response:\n\n```json\n{\n  \"tz_id\": \"Europe\u002FZurich\",\n  \"base_utc_offset\": 3600,\n  \"dst_offset\": 3600,\n  \"timestamp\": 1749479378,\n  \"local_rfc_2822_timestamp\": \"Mon, 9 Jun 2025 16:29:38 +0200\",\n  \"local_rfc_3389_timestamp\": \"2025-06-09T16:29:38+02:00\"\n}\n```\n\nNow AI models can immediately understand both the current local time and work with the format they parse most naturally. \nThis change also made the API more useful for human developers who previously had to calculate local time themselves.\n\n## Split Complex Endpoints into Focused Tools\n\nOur biggest breakthrough came from abandoning the one-tool-per-endpoint approach. \nInstead of exposing our every endpoint as a tool with many parameters, \nwe learned to split them into focused, use-case-specific tools, \noften removing complexity to ensure models can effectively use each tool.\n\nTake our [geocoding](\u002Fproducts\u002Fgeocoding-search\u002Fgeocoding\u002F) tool as an example. \nOriginally, we exposed all the filtering options available in our API—bounding box coordinates, \ncircular search areas, layer filters, and country restrictions. \nWe thought giving AI models more control would lead to better results.\n\nIn practice, the models never used most of these options, even when they should have. \nWhen they did try to use them, they often got confused about which filter was most appropriate and picked sub-optimal choices. \nA request to \"find coffee shops in downtown Seoul\" might trigger attempts to calculate bounding box coordinates rather than simply using the country filter.\n\nWe eventually eliminated everything except the country filter. \nWe kept this one because it was the simplest—just a 3-character ISO code rather than coordinate lists for bounding boxes or radius calculations. \nIt also happens that most models can figure out country codes quite easily from their pre-trained general knowledge, \nturning \"find addresses in South Korea\" into a simple `country: \"KOR\"` parameter.\n\nThe key insight: AI models perform better with multiple simple tools than one complex tool. \nThey can chain together focused tools to solve complex problems, \nbut they struggle to navigate a tool with dozens of configuration options. \nAs our tool usage grows, we expect to iteratively add new, \nfocused tools based on our existing endpoints to better help models answer location questions.\n\n## From Spectacular Failure to Working Tools\n\nThese four principles transformed our MCP server:\ncontextual tool descriptions, focused endpoint splitting, \nAI-optimized responses, and careful token management.\nAs we discovered them, the spectacular failure we described in our [first article](\u002Fblog\u002Fai-tools-for-api-companies-ai-needs-context\u002F) became something that actually works.\nAI models can now successfully help users find routes, geocode addresses, and interact with our location services in natural, intuitive ways.\n\nBut mastering the technical aspects of tool design was just the beginning. \nThe real surprises came from what we learned about our own APIs in the process, \nand the unexpected capabilities that emerged when AI agents started orchestrating our tools in ways we'd never anticipated.\n\nThese insights go far beyond tool design and touch on fundamental questions about how API companies should think about AI-native development, \ndeveloper experience, and business strategy in an agent-driven world.\n\nIn our next article, \nwe'll explore how building our MCP server became a mirror that revealed opportunities to improve our underlying APIs, \nand how it unlocked user workflows we never had to build ourselves. \nThe technical lessons covered here are essential, \nbut they're just the foundation for understanding what AI-native API consumption really means.\n\nFor now, if you're building your own tools for AI, \nstart with these principles and prepare to be surprised by what you learn about your own APIs in the process.\n\nWant to see these principles in action? \nCheck out our [MCP Server on GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-mcp-server-ts) and join our [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT) to discuss your own experiences with other developers tackling these same challenges.","TechArticle",{"title":549,"description":862},"blog\u002Fai-tools-for-api-companies-ai-native-design-principles","IxBvXvWaaZGfq92DBYQuHkB0on8eQYE8R19Nsl7c7yY",{"id":880,"title":881,"abstract":7,"author":7,"body":882,"description":1006,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":1007,"meta":1008,"modified":7,"navigation":187,"path":1009,"proficiencyLevel":872,"published":1010,"rawbody":1011,"schemaOrg":7,"schemaType":875,"seo":1012,"stem":1013,"__hash__":1014},"blog\u002Fblog\u002Fai-tools-for-api-companies-ai-needs-context.md","AI Tools for API Companies: AI Needs Context, or How Our Auto-Generation Failed Spectacularly",{"type":14,"value":883,"toc":999},[884,887,896,899,903,906,909,912,916,919,922,925,930,934,937,940,943,946,949,953,956,959,962,966,969,976,979,988],[17,885,881],{"id":886},"ai-tools-for-api-companies-ai-needs-context-or-how-our-auto-generation-failed-spectacularly",[24,888,889,890,895],{},"The AI agent revolution is here, and with it, everyone's talking about agent tools.\nAs a location API company, we've spent years perfecting location tools for human developers.\nSo when the ",[35,891,894],{"href":892,"rel":893,"target":40},"https:\u002F\u002Fmodelcontextprotocol.io\u002F",[39],"Model Context Protocol (MCP)"," promised to make our APIs accessible to AI agents,\nwe figured it would be straightforward.\nJust auto-generate a MCP server with a healthy selection of tools like we do with SDKs, right?",[24,897,898],{},"Wrong.\nOur initial attempts failed spectacularly,\nand we learned some unintuitive lessons:\nthe biggest of which is that the context in which AI consume APIs matters enormously.",[28,900,902],{"id":901},"what-are-ai-tools","What Are AI tools?",[24,904,905],{},"Fundamentally, tools are how language models interact with external systems.\nNormally, when a user asks an AI assistant to \"find the best route from Seoul to Busan,\"\nthe model can't give anything more than a vague summary.\nWith the right tools,\nhowever, AI can use APIs to lookup addresses, provide real-time directions, and even map the resulting path.",[24,907,908],{},"The Model Context Protocol standardizes how AI models discover and interact with these tools.\nMCP servers act as bridges between AI systems and external systems,\ndefining a consistent interface for tool discovery, parameter specification, and response handling.\nThey're gaining traction because they solve a critical infrastructure problem:\nhow to reliably connect AI agents to the vast ecosystem of existing APIs.",[24,910,911],{},"As engineers, this looked a lot like a pattern we already knew: SDKs for developers.",[28,913,915],{"id":914},"the-obvious-solution","The \"Obvious\" Solution",[24,917,918],{},"Given we'd already spent years building solid SDKs generated from hand-crafted OpenAPI specifications,\nit seemed logical to start there.\nFrom this foundation, we auto-generated our first MCP server.",[24,920,921],{},"From start to finish,\nthe whole process took a couple hours.\nWe had a working MCP server, complete with tools for geocoding, routing, and creating maps.\nIt seemed perfect.",[24,923,924],{},"Then we tried our prompt:",[21,926,927],{},[24,928,929],{},"Find the best route from Seoul to Busan.",[28,931,933],{"id":932},"what-happened","What Happened",[24,935,936],{},"Immediately, our quick win began showing its limits.\nThe models were using our tools in subtly but fundamentally flawed ways, and that’s the worst kind of failure.",[24,938,939],{},"Location APIs, even in the simplest form, are complex.\nMost endpoints offer dozens of inputs and parameters.\nFor humans, we solve this by offering clear documentation and guides.\nUnfortunately, this complexity quickly confused models.\nIn the maze of options, they couldn't figure out which parameters mattered.\nWhen finding a route should it optimize for time or distance?\nWhat about tolls?\nShould it choose car, bike, truck, some other mode of transportation?\nThis was further compounded by models not even knowing which questions to ask to feed the tool the right parameters.",[24,941,942],{},"Even when models did choose reasonable parameters, they struggled with complex responses.\nOur APIs return detailed JSON objects optimized for programmatic consumption,\nbut AI models often missed crucial information or got overwhelmed by unnecessary details.",[24,944,945],{},"Token consumption quickly became problematic.\nOur mega-tools with extensive parameter lists consumed large amounts of context space,\nleaving less room for user input and driving up model costs and, more importantly, efficiency.\nA single tool description could easily eat 500+ tokens before the model even chose which tool it should use.",[24,947,948],{},"The pattern was clear across every endpoint we tested:\nAPIs designed for human developers, no matter how well-crafted, don't automatically translate to effective AI tools.\nOur fundamental assumption—that well-built, well-documented APIs automatically make good AI tools—was completely wrong.",[28,950,952],{"id":951},"what-we-were-actually-building","What We Were Actually Building",[24,954,955],{},"We had to take a step back and consider what we were actually trying to do.",[24,957,958],{},"When we started, we assumed we were building another SDK, but we weren't.\nWe were building something fundamentally different: contextual tools specifically structured for AIs.\nThe key insight we missed initially is that AI models consume APIs through a completely different lens than human developers.",[24,960,961],{},"Human developers read documentation, understand business logic, and make nuanced decisions about parameter selection.\nAI models need tools designed specifically for their consumption patterns:\nfocused, well-described, and optimized for the constraints of language model reasoning.",[28,963,965],{"id":964},"whats-next","What's Next",[24,967,968],{},"This failure taught us much of what we needed to know about building MCP servers that actually work.\nAfter our auto-generated approach failed, we had to retool our entire strategy.",[24,970,557,971,975],{},[35,972,974],{"href":973},"\u002Fblog\u002Fai-tools-for-api-companies-ai-native-design-principles\u002F","next article",",\nwe'll share the design principles we discovered for creating AI-friendly tools,\nthe unexpected ways building MCPs improved our underlying APIs,\nand the new capabilities this unlocked that we never had to build ourselves.",[24,977,978],{},"For now, if you're looking at MCPs for your own API company, remember this:\nthe obvious solution rarely works when you're building for AI consumption.\nThe patterns that make APIs great for human developers need fundamental rethinking for AI agents.",[24,980,981,982,987],{},"Want to stay ahead of the AI tooling curve?\n",[35,983,986],{"href":984,"rel":985,"target":40},"https:\u002F\u002Fmailchi.mp\u002Fstadiamaps\u002Fmcp-leads-landing",[39],"Subscribe to our newsletter"," for insights on building APIs that work seamlessly with AI agents,\nMCP server best practices, and the evolving landscape of AI-native development.",[24,989,990,991,994,995,998],{},"If you're impatient and want to see our principles in action right now,\ncheck out our ",[35,992,843],{"href":841,"rel":993,"target":40},[39],".\nAnd join our ",[35,996,849],{"href":847,"rel":997,"target":40},[39]," to discuss your own MCP experiences with other developers tackling these same challenges.",{"title":168,"searchDepth":169,"depth":169,"links":1000},[1001,1002,1003,1004,1005],{"id":901,"depth":172,"text":902},{"id":914,"depth":172,"text":915},{"id":932,"depth":172,"text":933},{"id":951,"depth":172,"text":952},{"id":964,"depth":172,"text":965},"Why our obvious approach to building MCP servers failed spectacularly,  and what we learned about AI-native API consumption. This is the first post in our series about AI tools for API companies.",[864,865,866,867,868],{},"\u002Fblog\u002Fai-tools-for-api-companies-ai-needs-context","2025-08-01","---\ndescription: >-\n  Why our obvious approach to building MCP servers failed spectacularly, \n  and what we learned about AI-native API consumption.\n  This is the first post in our series about AI tools for API companies.\npublished: \"2025-08-01\"\nkeywords:\n  - AI\n  - MCP\n  - Model Context Protocol\n  - API Design\n  - AI Agents\nschemaType: TechArticle\nproficiencyLevel: Expert\n---\n\n# AI Tools for API Companies: AI Needs Context, or How Our Auto-Generation Failed Spectacularly\n\nThe AI agent revolution is here, and with it, everyone's talking about agent tools.\nAs a location API company, we've spent years perfecting location tools for human developers.\nSo when the [Model Context Protocol (MCP)](https:\u002F\u002Fmodelcontextprotocol.io\u002F) promised to make our APIs accessible to AI agents, \nwe figured it would be straightforward.\nJust auto-generate a MCP server with a healthy selection of tools like we do with SDKs, right?\n\nWrong. \nOur initial attempts failed spectacularly, \nand we learned some unintuitive lessons: \nthe biggest of which is that the context in which AI consume APIs matters enormously.\n\n## What Are AI tools?\n\nFundamentally, tools are how language models interact with external systems.\nNormally, when a user asks an AI assistant to \"find the best route from Seoul to Busan,\" \nthe model can't give anything more than a vague summary.\nWith the right tools, \nhowever, AI can use APIs to lookup addresses, provide real-time directions, and even map the resulting path.\n\nThe Model Context Protocol standardizes how AI models discover and interact with these tools.\nMCP servers act as bridges between AI systems and external systems, \ndefining a consistent interface for tool discovery, parameter specification, and response handling. \nThey're gaining traction because they solve a critical infrastructure problem: \nhow to reliably connect AI agents to the vast ecosystem of existing APIs.\n\nAs engineers, this looked a lot like a pattern we already knew: SDKs for developers.\n\n## The \"Obvious\" Solution\n\nGiven we'd already spent years building solid SDKs generated from hand-crafted OpenAPI specifications, \nit seemed logical to start there. \nFrom this foundation, we auto-generated our first MCP server.\n\nFrom start to finish, \nthe whole process took a couple hours. \nWe had a working MCP server, complete with tools for geocoding, routing, and creating maps. \nIt seemed perfect.\n\nThen we tried our prompt:\n\n> Find the best route from Seoul to Busan.\n\n## What Happened\n\nImmediately, our quick win began showing its limits. \nThe models were using our tools in subtly but fundamentally flawed ways, and that’s the worst kind of failure.\n\nLocation APIs, even in the simplest form, are complex. \nMost endpoints offer dozens of inputs and parameters. \nFor humans, we solve this by offering clear documentation and guides. \nUnfortunately, this complexity quickly confused models. \nIn the maze of options, they couldn't figure out which parameters mattered. \nWhen finding a route should it optimize for time or distance? \nWhat about tolls? \nShould it choose car, bike, truck, some other mode of transportation? \nThis was further compounded by models not even knowing which questions to ask to feed the tool the right parameters.\n\nEven when models did choose reasonable parameters, they struggled with complex responses. \nOur APIs return detailed JSON objects optimized for programmatic consumption, \nbut AI models often missed crucial information or got overwhelmed by unnecessary details.\n\nToken consumption quickly became problematic. \nOur mega-tools with extensive parameter lists consumed large amounts of context space, \nleaving less room for user input and driving up model costs and, more importantly, efficiency. \nA single tool description could easily eat 500+ tokens before the model even chose which tool it should use.\n\nThe pattern was clear across every endpoint we tested: \nAPIs designed for human developers, no matter how well-crafted, don't automatically translate to effective AI tools. \nOur fundamental assumption—that well-built, well-documented APIs automatically make good AI tools—was completely wrong.\n\n## What We Were Actually Building\n\nWe had to take a step back and consider what we were actually trying to do.\n\nWhen we started, we assumed we were building another SDK, but we weren't. \nWe were building something fundamentally different: contextual tools specifically structured for AIs. \nThe key insight we missed initially is that AI models consume APIs through a completely different lens than human developers.\n\nHuman developers read documentation, understand business logic, and make nuanced decisions about parameter selection.\nAI models need tools designed specifically for their consumption patterns: \nfocused, well-described, and optimized for the constraints of language model reasoning.\n\n## What's Next\n\nThis failure taught us much of what we needed to know about building MCP servers that actually work. \nAfter our auto-generated approach failed, we had to retool our entire strategy.\n\nIn our [next article](\u002Fblog\u002Fai-tools-for-api-companies-ai-native-design-principles\u002F), \nwe'll share the design principles we discovered for creating AI-friendly tools, \nthe unexpected ways building MCPs improved our underlying APIs, \nand the new capabilities this unlocked that we never had to build ourselves.\n\nFor now, if you're looking at MCPs for your own API company, remember this: \nthe obvious solution rarely works when you're building for AI consumption. \nThe patterns that make APIs great for human developers need fundamental rethinking for AI agents.\n\nWant to stay ahead of the AI tooling curve? \n[Subscribe to our newsletter](https:\u002F\u002Fmailchi.mp\u002Fstadiamaps\u002Fmcp-leads-landing) for insights on building APIs that work seamlessly with AI agents, \nMCP server best practices, and the evolving landscape of AI-native development.\n\nIf you're impatient and want to see our principles in action right now, \ncheck out our [MCP Server on GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-mcp-server-ts). \nAnd join our [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT) to discuss your own MCP experiences with other developers tackling these same challenges.",{"title":881,"description":1006},"blog\u002Fai-tools-for-api-companies-ai-needs-context","9HzTfxCNJpNp_3tSsRsxs8JoouIv1e8Ivy4u9S7KkA0",{"id":1016,"title":1017,"abstract":7,"author":7,"body":1018,"description":1285,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":1286,"meta":1291,"modified":7,"navigation":187,"path":1292,"proficiencyLevel":7,"published":1293,"rawbody":1294,"schemaOrg":7,"schemaType":7,"seo":1295,"stem":1296,"__hash__":1297},"blog\u002Fblog\u002Fgeocoding-and-autocomplete-v2-updates-continue.md","Enriching Geocoding & Search: More Data, Smarter Deduplication, and Forward & Reverse v2",{"type":14,"value":1019,"toc":1272},[1020,1023,1026,1043,1047,1050,1060,1064,1067,1078,1081,1084,1088,1098,1104,1108,1111,1128,1132,1143,1147,1150,1152,1161,1165,1168,1198,1201,1204,1209,1218,1220,1224,1227],[17,1021,1017],{"id":1022},"enriching-geocoding-search-more-data-smarter-deduplication-and-forward-reverse-v2",[24,1024,1025],{},"On the heels of our last geocoding update for our Autocomplete and Place Details endpoints,\nwe're excited to announce another major update to Geocoding & Search:",[56,1027,1028,1031,1034,1037,1040],{},[59,1029,1030],{},"v2 of our Forward and Reverse geocoding endpoints,",[59,1032,1033],{},"label improvements for v1 endpoints,",[59,1035,1036],{},"enhancements to Autocomplete deduplication,",[59,1038,1039],{},"a collection of multi-language improvements,",[59,1041,1042],{},"and another significant Foursquare OS Places update.",[28,1044,1046],{"id":1045},"new-address-delimiter-parsing-in-forward-geocoding","New Address Delimiter Parsing in Forward Geocoding",[24,1048,1049],{},"We've improved how we handle delimiters for house and building numbers, and their different ways they are represented around the world.",[24,1051,1052,1053,1056,1057,458],{},"With this update,\nyou can now easily and more accurately search for addresses such as ",[349,1054,1055],{},"Telliskivi 60a\u002F3, Tallinn"," or ",[349,1058,1059],{},"Kossuth Lajos utca 20. IV\u002F15, 1053 Budapest, Hungary",[28,1061,1063],{"id":1062},"improved-regional-context-with-reverse-geocoding","Improved Regional Context with Reverse Geocoding",[24,1065,1066],{},"Full contextual hierarchy is now available in all Reverse Geocoding responses,\nproviding a straightforward path when you care about the context rather than a specific physical feature (e.g., in coarse lookups).",[24,1068,1069,1070,1073,1074,1077],{},"Previously,\nthe ",[349,1071,1072],{},"\u002Freverse"," endpoint behavior depended on which layers you explicitly included.\nWhen searching for an address, street, or venue (POI),\nwe served up the full context: locality, region, country, and so on.\nBut for a coarse lookup,\nthe API only included layers you ",[611,1075,1076],{},"explicitly"," specified and dropped everything else (e.g., country code).",[24,1079,1080],{},"We have fixed this in both v1 and v2,\nand all responses include a complete contextual hierarchy,\nregardless of your search.\nThis response style matches the way our other search endpoints work and does not break any assumptions about result ordering.",[24,1082,1083],{},"With v2, just like v1, you'll receive the most granular layer result first based on your query.",[28,1085,1087],{"id":1086},"better-label-responses-in-v1-endpoints","Better Label Responses in v1 Endpoints",[24,1089,1090,1091,1094,1095,458],{},"Labels generated from the Who's on First source are now much more sensible for places across the globe.\nFor instance, where the API used to return ",[349,1092,1093],{},"Seoul, Yongsan-gu, Seoul, South Korea",",\nwe now simply return ",[349,1096,1097],{},"Seoul, South Korea",[24,1099,1100,1101,458],{},"All v1 APIs now include this improvement except ",[349,1102,1103],{},"\u002Fv1\u002Fsearch\u002Fstructured",[28,1105,1107],{"id":1106},"deduplication-and-more-relevance-in-autocomplete","Deduplication and More Relevance in Autocomplete",[24,1109,1110],{},"Our Autocomplete API enables seamless searching across many sources,\nincluding Foursquare OS Places, Geonames, OpenStreetMap, OpenAddresses, and Who's On First.\nWhile using such a broad range of sources ensures we have the best global coverage,\nit presents a deduplication problem when a location is present in multiple sources.\nWith our smarter deduplication process,\nwe’ve eliminated duplicate results across a range of location types:",[56,1112,1113,1116,1119,1122,1125],{},[59,1114,1115],{},"Tighter deduplication of addresses across our datasets;",[59,1117,1118],{},"Leveraging the ease of edits in OpenStreetMap, OSM addresses are now preferred over other sources when there is a collision;",[59,1120,1121],{},"More relevant results for focused searches, especially when searching for dense chains like 7-Eleven or Starbucks;",[59,1123,1124],{},"East Asian language deduplication improvements when comparing inconsistent naming between sources;",[59,1126,1127],{},"Better deduplication of place names with exotic Unicode representation (e.g., a stylized \"𝐀𝐂𝐌𝐄, 𝐈𝐍𝐂.\" is considered the same as \"ACME, Inc.\")",[28,1129,1131],{"id":1130},"multi-language-query-improvements","Multi-Language Query Improvements",[24,1133,1134,1135,1138,1139,1142],{},"We updated the v1 and v2 ",[349,1136,1137],{},"\u002Fsearch"," endpoint to take into account the ",[349,1140,1141],{},"lang"," parameter when querying for POIs,\nimproving the quality of multilingual name searches.\nPreviously, if you were querying POI names in another language (e.g., the English name of a cafe whose primary name is Korean),\nyou would receive zero results when using Search.",[28,1144,1146],{"id":1145},"foursquare-os-places-update","Foursquare OS Places Update",[24,1148,1149],{},"We have now included an additional 8 million places from Foursquare OS Places,\nbringing the total number of available POIs from Foursquare to about 14 million.",[28,1151,428],{"id":427},[24,1153,1154,1155,1160],{},"All of these improvements are available for you today!\nIf you're using our ",[35,1156,1159],{"href":1157,"rel":1158,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement&utm_content=sdk_cta",[39],"SDKs",",\nupdate to the latest version.",[28,1162,1164],{"id":1163},"learn-more-and-get-started","Learn More and Get Started",[24,1166,1167],{},"Ready to experience the power of Geocoding & Search v2?\nHere are some helpful resources to get you started:",[56,1169,1170,1177,1184,1191],{},[59,1171,1172],{},[35,1173,1176],{"href":1174,"rel":1175,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement#autocomplete-search",[39],"Autocomplete Search SDKs",[59,1178,1179],{},[35,1180,1183],{"href":1181,"rel":1182,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement&utm_content=sdk_reference",[39],"API Clients\u002FSDKs",[59,1185,1186],{},[35,1187,1190],{"href":1188,"rel":1189,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fv2-api-migration-guide\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement",[39],"v2 Migration Guide for Developers",[59,1192,1193],{},[35,1194,1197],{"href":1195,"rel":1196,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement&utm_content=foursquare_beta_next_steps",[39],"Geocoding Documentation",[24,1199,1200],{},"We're confident Geocoding & Search v2 will significantly enhance your ability to build location-aware applications.\nWith more data and improved results,\nit's never been a better time to leverage the power of location with Stadia Maps.",[24,1202,1203],{},"Start exploring today and unlock the full potential of location search in your current or next project!",[1205,1206,1208],"h3",{"id":1207},"account-and-api-key","Account and API Key",[24,1210,1211,1212,1217],{},"If you don’t already have an account,\n",[35,1213,1216],{"href":1214,"rel":1215,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement",[39],"create an account"," to start building today—no credit card is required.",[152,1219],{},[28,1221,1223],{"id":1222},"stadia-maps-community","Stadia Maps Community",[24,1225,1226],{},"Stay connected with Stadia Maps:",[56,1228,1229,1241],{},[59,1230,1231,1232,1056,1235,1240],{},"Join our community on ",[35,1233,849],{"href":847,"rel":1234,"target":40},[39],[35,1236,1239],{"href":1237,"rel":1238,"target":40},"https:\u002F\u002Fslack.openstreetmap.us\u002F",[39],"Slack"," to share what you're working on or get help.",[59,1242,1243,1244,352,1249,352,1254,1259,1260,1265,1266,1271],{},"Follow us on ",[35,1245,1248],{"href":1246,"rel":1247,"target":40},"https:\u002F\u002Fen.osm.town\u002F@stadiamaps",[39],"Mastodon",[35,1250,1253],{"href":1251,"rel":1252,"target":40},"https:\u002F\u002Ftwitter.com\u002F@stadiamaps",[39],"Twitter",[35,1255,1258],{"href":1256,"rel":1257,"target":40},"https:\u002F\u002Fbsky.app\u002Fprofile\u002Fstadiamaps.com",[39],"BlueSky",", or ",[35,1261,1264],{"href":1262,"rel":1263,"target":40},"https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F",[39],"LinkedIn",", or sign up for our ",[35,1267,1270],{"href":1268,"rel":1269,"target":40},"https:\u002F\u002Feepurl.com\u002Fgs51fD",[39],"mailing list"," to stay up to date.",{"title":168,"searchDepth":169,"depth":169,"links":1273},[1274,1275,1276,1277,1278,1279,1280,1281,1284],{"id":1045,"depth":172,"text":1046},{"id":1062,"depth":172,"text":1063},{"id":1086,"depth":172,"text":1087},{"id":1106,"depth":172,"text":1107},{"id":1130,"depth":172,"text":1131},{"id":1145,"depth":172,"text":1146},{"id":427,"depth":172,"text":428},{"id":1163,"depth":172,"text":1164,"children":1282},[1283],{"id":1207,"depth":669,"text":1208},{"id":1222,"depth":172,"text":1223},"Our latest geocoding update includes v2 of Forward and Reverse endpoints, smarter deduplication, better multi-language support, and more Foursquare OS Places data.",[402,1287,1288,1289,1290],"Reverse Geocoding","Forward Geocoding","API Update","Foursquare",{},"\u002Fblog\u002Fgeocoding-and-autocomplete-v2-updates-continue","2025-07-01","---\ndescription: \"Our latest geocoding update includes v2 of Forward and Reverse endpoints, smarter deduplication, better multi-language support, and more Foursquare OS Places data.\"\npublished: \"2025-07-01\"\nkeywords:\n  - Geocoding\n  - Reverse Geocoding\n  - Forward Geocoding\n  - API Update\n  - Foursquare\n---\n\n# Enriching Geocoding & Search: More Data, Smarter Deduplication, and Forward & Reverse v2\n\nOn the heels of our last geocoding update for our Autocomplete and Place Details endpoints, \nwe're excited to announce another major update to Geocoding & Search:\n\n* v2 of our Forward and Reverse geocoding endpoints, \n* label improvements for v1 endpoints,\n* enhancements to Autocomplete deduplication, \n* a collection of multi-language improvements, \n* and another significant Foursquare OS Places update.\n\n## New Address Delimiter Parsing in Forward Geocoding\n\nWe've improved how we handle delimiters for house and building numbers, and their different ways they are represented around the world.\n\nWith this update, \nyou can now easily and more accurately search for addresses such as `Telliskivi 60a\u002F3, Tallinn` or `Kossuth Lajos utca 20. IV\u002F15, 1053 Budapest, Hungary`.\n\n## Improved Regional Context with Reverse Geocoding\n\nFull contextual hierarchy is now available in all Reverse Geocoding responses,\nproviding a straightforward path when you care about the context rather than a specific physical feature (e.g., in coarse lookups).\n\nPreviously, \nthe `\u002Freverse` endpoint behavior depended on which layers you explicitly included.\nWhen searching for an address, street, or venue (POI),\nwe served up the full context: locality, region, country, and so on.\nBut for a coarse lookup,\nthe API only included layers you _explicitly_ specified and dropped everything else (e.g., country code).\n\nWe have fixed this in both v1 and v2, \nand all responses include a complete contextual hierarchy,\nregardless of your search.\nThis response style matches the way our other search endpoints work and does not break any assumptions about result ordering.\n\nWith v2, just like v1, you'll receive the most granular layer result first based on your query.\n\n## Better Label Responses in v1 Endpoints\n\nLabels generated from the Who's on First source are now much more sensible for places across the globe.\nFor instance, where the API used to return `Seoul, Yongsan-gu, Seoul, South Korea`,\nwe now simply return `Seoul, South Korea`.\n\nAll v1 APIs now include this improvement except `\u002Fv1\u002Fsearch\u002Fstructured`.\n\n## Deduplication and More Relevance in Autocomplete\n\nOur Autocomplete API enables seamless searching across many sources,\nincluding Foursquare OS Places, Geonames, OpenStreetMap, OpenAddresses, and Who's On First.\nWhile using such a broad range of sources ensures we have the best global coverage,\nit presents a deduplication problem when a location is present in multiple sources.\nWith our smarter deduplication process,\nwe’ve eliminated duplicate results across a range of location types:\n\n* Tighter deduplication of addresses across our datasets;  \n* Leveraging the ease of edits in OpenStreetMap, OSM addresses are now preferred over other sources when there is a collision;  \n* More relevant results for focused searches, especially when searching for dense chains like 7-Eleven or Starbucks;  \n* East Asian language deduplication improvements when comparing inconsistent naming between sources;  \n* Better deduplication of place names with exotic Unicode representation (e.g., a stylized \"𝐀𝐂𝐌𝐄, 𝐈𝐍𝐂.\" is considered the same as \"ACME, Inc.\")\n\n## Multi-Language Query Improvements\n\nWe updated the v1 and v2 `\u002Fsearch` endpoint to take into account the `lang` parameter when querying for POIs,\nimproving the quality of multilingual name searches.\nPreviously, if you were querying POI names in another language (e.g., the English name of a cafe whose primary name is Korean),\nyou would receive zero results when using Search.\n\n## Foursquare OS Places Update\n\nWe have now included an additional 8 million places from Foursquare OS Places,\nbringing the total number of available POIs from Foursquare to about 14 million.\n\n## Available Today\n\nAll of these improvements are available for you today!\nIf you're using our [SDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement&utm_content=sdk_cta),\nupdate to the latest version.\n\n## Learn More and Get Started\n\nReady to experience the power of Geocoding & Search v2?\nHere are some helpful resources to get you started:\n\n* [Autocomplete Search SDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement#autocomplete-search)  \n* [API Clients\u002FSDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement&utm_content=sdk_reference)  \n* [v2 Migration Guide for Developers](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fv2-api-migration-guide\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement)  \n* [Geocoding Documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement&utm_content=foursquare_beta_next_steps)\n\nWe're confident Geocoding & Search v2 will significantly enhance your ability to build location-aware applications.\nWith more data and improved results,\nit's never been a better time to leverage the power of location with Stadia Maps.\n\nStart exploring today and unlock the full potential of location search in your current or next project!\n\n### Account and API Key\n\nIf you don’t already have an account,\n[create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_v2_improvements_announcement) to start building today—no credit card is required.\n\n---\n\n## Stadia Maps Community\n\nStay connected with Stadia Maps:\n\n* Join our community on [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT) or [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) to share what you're working on or get help.  \n* Follow us on [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps), [BlueSky](https:\u002F\u002Fbsky.app\u002Fprofile\u002Fstadiamaps.com), or [LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign up for our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD) to stay up to date.\n",{"title":1017,"description":1285},"blog\u002Fgeocoding-and-autocomplete-v2-updates-continue","beUtzdbAtu9GeBSvg2SvA62JIg59q6Lhy3GWpYFqCrM",{"id":1299,"title":1300,"abstract":7,"author":7,"body":1301,"description":1505,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":1506,"meta":1510,"modified":7,"navigation":187,"path":1511,"proficiencyLevel":7,"published":1512,"rawbody":1513,"schemaOrg":7,"schemaType":7,"seo":1514,"stem":1515,"__hash__":1516},"blog\u002Fblog\u002Fintroducing-stadia-maps-geocoding-search-v2.md","Introducing Stadia Maps Geocoding & Search v2: Supercharge Your Search",{"type":14,"value":1302,"toc":1498},[1303,1306,1309,1317,1320,1332,1336,1339,1359,1363,1366,1384,1387,1391,1394,1433,1436,1439,1465,1467,1470,1492,1495],[17,1304,1300],{"id":1305},"introducing-stadia-maps-geocoding-search-v2-supercharge-your-search",[24,1307,1308],{},"At Stadia Maps, we're dedicated to helping millions of users find their perfect starting point every month with our powerful Autocomplete Search.\nToday, we're thrilled to announce a significant upgrade: Geocoding & Search v2!",[24,1310,1311,1312,1316],{},"The latest version of ",[35,1313,1315],{"href":1314},"\u002Fproducts\u002Fgeocoding-search\u002F","Stadia Maps Geocoding & Search"," isn't just an incremental update;\nit's a significant leap forward.\nWe've integrated millions more places and addresses,\nachieved faster API responses,\nand delivered better, more relevant results with enhanced language support—especially for non-English queries.",[24,1318,1319],{},"Additionally, we're introducing a new API and billing structure for Autocomplete,\ndesigned to make this essential feature even more accessible.\nThis new structure enables us to reduce the cost of a typical session by almost 80%,\nmaking it more affordable for everyone.",[24,1321,1322,1323,1325,1326,1331],{},"And that's not all!\nWe're also making Geocoding & Search more accessible for everyone.\n",[35,1324,1288],{"href":797}," and\n",[35,1327,1330],{"href":1328,"rel":1329,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fplace-details\u002F?utm_source=marketing_site&utm_campaign=geocoding_v2_launch_announcement",[39],"Place Details","\nare now available to all users, even if you're on the Free plan.",[28,1333,1335],{"id":1334},"more-data-more-possibilities","More Data, More Possibilities",[24,1337,1338],{},"We're all about providing you with the most comprehensive and accurate location data.\nWith Geocoding & Search v2, we've significantly expanded our horizons:",[56,1340,1341,1347],{},[59,1342,1343,1346],{},[62,1344,1345],{},"Expanded address coverage:"," We've added 4 million more addresses worldwide.\nWhat does this mean for you? Simply put, more people will be able to find the exact addresses they're looking for.",[59,1348,1349,1352,1353,1358],{},[62,1350,1351],{},"Foursquare integration:","\nWe've integrated ",[35,1354,1357],{"href":1355,"rel":1356,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fblog\u002Fgeocoding-foursquare-beta\u002F",[39],"Foursquare's Places"," dataset,\nadding over 10 million records to our existing robust sources (OpenStreetMap, OpenAddresses, and GeoNames).\nBy carefully integrating and deduplicating this massive dataset,\nwe're enriching our place information and ensuring you get the most comprehensive results.",[28,1360,1362],{"id":1361},"smarter-pricing-for-autocomplete-making-it-even-more-affordable","Smarter Pricing for Autocomplete: Making It Even More Affordable",[24,1364,1365],{},"We understand that efficient and cost-effective tools are crucial.\nThat's why we've completely revamped our Autocomplete pricing model to better align with the value it delivers,\nmaking it a smart investment for your business.",[56,1367,1368,1374],{},[59,1369,1370,1373],{},[62,1371,1372],{},"Nominal costs while typing:"," While a user searches, each API call will now cost only 1 credit (down from 20\ncredits!). This means you can provide instant feedback to your users without worrying about high costs.",[59,1375,1376,1379,1380,1383],{},[62,1377,1378],{},"Standard cost on selection:"," Once the user selects a result, you can easily retrieve the full details using the\n",[349,1381,1382],{},"\u002Fplace_details"," endpoint, and the standard cost of 20 credits will apply.",[24,1385,1386],{},"This fundamental shift in pricing makes our powerful Autocomplete endpoints accessible to a wider range of users and\napplications, and—finally—the economics make sense.",[28,1388,1390],{"id":1389},"better-results-improved-accuracy-relevance-and-language-precision","Better Results: Improved Accuracy, Relevance, and Language Precision",[24,1392,1393],{},"We're committed to delivering the best possible search experience.\nWith Geocoding & Search v2, you'll notice significant improvements in result quality.",[56,1395,1396,1402,1408,1421,1427],{},[59,1397,1398,1401],{},[62,1399,1400],{},"Enhanced multilingual support:"," We improved accuracy and relevance when searching in languages other than English,\nensuring a more inclusive and comprehensive search experience for all users.",[59,1403,1404,1407],{},[62,1405,1406],{},"Smarter Deduplication:"," We've tackled the tricky issue of deduplicating similar Points of Interest (POIs).\nWe've squashed bugs and implemented smarter logic,\nresulting in a cleaner and more intuitive search experience for all searches.",[59,1409,1410,1413,1414,1416,1417,1420],{},[62,1411,1412],{},"Reduced Bias for English:"," We've removed the assumption of English as the default language, meaning requests\nwithout a ",[349,1415,1141],{}," query parameter or an ",[349,1418,1419],{},"Accept-Language"," header will yield more accurate results in the relevant local\nlanguage.",[59,1422,1423,1426],{},[62,1424,1425],{},"Foursquare Data Advantage:"," Integrating Foursquare data provides us with richer information about each place,\nallowing us to understand and conflate data from various sources better, ultimately leading to more relevant and\ninformative results.",[59,1428,1429,1432],{},[62,1430,1431],{},"Better, Faster Responses",": The v2 autocomplete endpoint includes a streamlined response format with everything you\nneed to build the UI and an ID you can use to look up the full details.",[28,1434,1435],{"id":964},"What's Next?",[24,1437,1438],{},"This is just the beginning! We're excited about the future of Stadia Maps Geocoding & Search.\nHere's a sneak peek into what else we’re working on.",[56,1440,1441,1447,1453,1459],{},[59,1442,1443,1446],{},[62,1444,1445],{},"Additional endpoints:"," The rest of our Geocoding endpoints will also be upgraded to v2, benefiting from the new\ninfrastructure and improvements.",[59,1448,1449,1452],{},[62,1450,1451],{},"Continued improvements for v1:"," We're not forgetting our existing Geocoding & Search v1 users. We’ve already rolled\nout many of the improvements to v1, and we will continue applying as many improvements as possible to the current\nendpoints, ensuring everyone benefits from our enhanced data.",[59,1454,1455,1458],{},[62,1456,1457],{},"Updated SDKs:"," We have already updated our SDKs to use the new Autocomplete API.\nUpgrade today to start saving!",[59,1460,1461,1464],{},[62,1462,1463],{},"More datasets:"," We're constantly exploring and integrating new datasets further to enhance the accuracy and\ncoverage of our services.",[28,1466,1164],{"id":1163},[24,1468,1469],{},"Ready to experience the power of Geocoding & Search v2? Here are some helpful resources:",[56,1471,1472,1478,1485],{},[59,1473,1474],{},[35,1475,1176],{"href":1476,"rel":1477,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_campaign=geocoding_v2_launch_announcement#autocomplete-search",[39],[59,1479,1480],{},[35,1481,1484],{"href":1482,"rel":1483,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F",[39],"API Clients",[59,1486,1487],{},[35,1488,1491],{"href":1489,"rel":1490,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fv2-api-migration-guide\u002F?utm_source=marketing_site&utm_campaign=geocoding_v2_launch_announcement",[39],"Transition Guide for Developers",[24,1493,1494],{},"We're confident that Geocoding & Search v2 will significantly enhance how you build location-aware applications.\nWith more data, smarter pricing, and better results, it's never been a better time to leverage the power of Stadia Maps.",[24,1496,1497],{},"Start exploring today and unlock the full potential of location search!",{"title":168,"searchDepth":169,"depth":169,"links":1499},[1500,1501,1502,1503,1504],{"id":1334,"depth":172,"text":1335},{"id":1361,"depth":172,"text":1362},{"id":1389,"depth":172,"text":1390},{"id":964,"depth":172,"text":1435},{"id":1163,"depth":172,"text":1164},"Smarter, faster, cheaper Search is here!  We're adding 14M+ new places & addresses,  serving faster & more accurate results,  reducing autocomplete costs by 80%,  and making forward geocoding available for everyone.",[402,1507,1289,1508,1509],"Autocomplete Search","Place Search","Address Search",{},"\u002Fblog\u002Fintroducing-stadia-maps-geocoding-search-v2","2025-04-08","---\npublished: \"2025-04-08\"\ndescription: >- \n  Smarter, faster, cheaper Search is here! \n  We're adding 14M+ new places & addresses, \n  serving faster & more accurate results, \n  reducing autocomplete costs by 80%, \n  and making forward geocoding available for everyone.\nkeywords:\n  - Geocoding\n  - Autocomplete Search\n  - API Update\n  - Place Search\n  - Address Search\n---\n\n# Introducing Stadia Maps Geocoding & Search v2: Supercharge Your Search\n\nAt Stadia Maps, we're dedicated to helping millions of users find their perfect starting point every month with our powerful Autocomplete Search.\nToday, we're thrilled to announce a significant upgrade: Geocoding & Search v2!\n\nThe latest version of [Stadia Maps Geocoding & Search](\u002Fproducts\u002Fgeocoding-search\u002F) isn't just an incremental update; \nit's a significant leap forward. \nWe've integrated millions more places and addresses, \nachieved faster API responses, \nand delivered better, more relevant results with enhanced language support—especially for non-English queries.\n\nAdditionally, we're introducing a new API and billing structure for Autocomplete, \ndesigned to make this essential feature even more accessible. \nThis new structure enables us to reduce the cost of a typical session by almost 80%, \nmaking it more affordable for everyone.\n\nAnd that's not all!\nWe're also making Geocoding & Search more accessible for everyone.\n[Forward Geocoding](\u002Fproducts\u002Fgeocoding-search\u002Fgeocoding\u002F) and\n[Place Details](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fplace-details\u002F?utm_source=marketing_site&utm_campaign=geocoding_v2_launch_announcement) \nare now available to all users, even if you're on the Free plan.\n\n## More Data, More Possibilities\n\nWe're all about providing you with the most comprehensive and accurate location data. \nWith Geocoding & Search v2, we've significantly expanded our horizons:\n\n* **Expanded address coverage:** We've added 4 million more addresses worldwide.\n  What does this mean for you? Simply put, more people will be able to find the exact addresses they're looking for.\n\n* **Foursquare integration:** \n  We've integrated [Foursquare's Places](https:\u002F\u002Fstadiamaps.com\u002Fblog\u002Fgeocoding-foursquare-beta\u002F) dataset, \n  adding over 10 million records to our existing robust sources (OpenStreetMap, OpenAddresses, and GeoNames). \n  By carefully integrating and deduplicating this massive dataset, \n  we're enriching our place information and ensuring you get the most comprehensive results.\n\n## Smarter Pricing for Autocomplete: Making It Even More Affordable\n\nWe understand that efficient and cost-effective tools are crucial. \nThat's why we've completely revamped our Autocomplete pricing model to better align with the value it delivers, \nmaking it a smart investment for your business.\n\n* **Nominal costs while typing:** While a user searches, each API call will now cost only 1 credit (down from 20\n  credits!). This means you can provide instant feedback to your users without worrying about high costs.\n\n* **Standard cost on selection:** Once the user selects a result, you can easily retrieve the full details using the\n  `\u002Fplace_details` endpoint, and the standard cost of 20 credits will apply.\n\nThis fundamental shift in pricing makes our powerful Autocomplete endpoints accessible to a wider range of users and\napplications, and—finally—the economics make sense.\n\n## Better Results: Improved Accuracy, Relevance, and Language Precision\n\nWe're committed to delivering the best possible search experience.\nWith Geocoding & Search v2, you'll notice significant improvements in result quality.\n\n* **Enhanced multilingual support:** We improved accuracy and relevance when searching in languages other than English,\n  ensuring a more inclusive and comprehensive search experience for all users.\n\n* **Smarter Deduplication:** We've tackled the tricky issue of deduplicating similar Points of Interest (POIs). \n  We've squashed bugs and implemented smarter logic, \n  resulting in a cleaner and more intuitive search experience for all searches.\n\n* **Reduced Bias for English:** We've removed the assumption of English as the default language, meaning requests\n  without a `lang` query parameter or an `Accept-Language` header will yield more accurate results in the relevant local\n  language.\n\n* **Foursquare Data Advantage:** Integrating Foursquare data provides us with richer information about each place,\n  allowing us to understand and conflate data from various sources better, ultimately leading to more relevant and\n  informative results.\n\n* **Better, Faster Responses**: The v2 autocomplete endpoint includes a streamlined response format with everything you\n  need to build the UI and an ID you can use to look up the full details.\n\n## What's Next?\n\nThis is just the beginning! We're excited about the future of Stadia Maps Geocoding & Search. \nHere's a sneak peek into what else we’re working on.\n\n* **Additional endpoints:** The rest of our Geocoding endpoints will also be upgraded to v2, benefiting from the new\n  infrastructure and improvements.\n\n* **Continued improvements for v1:** We're not forgetting our existing Geocoding & Search v1 users. We’ve already rolled\n  out many of the improvements to v1, and we will continue applying as many improvements as possible to the current\n  endpoints, ensuring everyone benefits from our enhanced data.\n\n* **Updated SDKs:** We have already updated our SDKs to use the new Autocomplete API.\n  Upgrade today to start saving!\n\n* **More datasets:** We're constantly exploring and integrating new datasets further to enhance the accuracy and\n  coverage of our services.\n\n## Learn More and Get Started\n\nReady to experience the power of Geocoding & Search v2? Here are some helpful resources:\n\n* [Autocomplete Search SDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_campaign=geocoding_v2_launch_announcement#autocomplete-search)\n* [API Clients](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F)\n* [Transition Guide for Developers](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fv2-api-migration-guide\u002F?utm_source=marketing_site&utm_campaign=geocoding_v2_launch_announcement)\n\nWe're confident that Geocoding & Search v2 will significantly enhance how you build location-aware applications. \nWith more data, smarter pricing, and better results, it's never been a better time to leverage the power of Stadia Maps.\n\nStart exploring today and unlock the full potential of location search!",{"title":1300,"description":1505},"blog\u002Fintroducing-stadia-maps-geocoding-search-v2","0lkA0y9eUgy2z4UoAwiy3PAe1OiU5i2glhiOF3gU5j4",{"id":1518,"title":1519,"abstract":7,"author":7,"body":1520,"description":1641,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":1642,"meta":1643,"modified":7,"navigation":187,"path":1644,"proficiencyLevel":7,"published":1645,"rawbody":1646,"schemaOrg":7,"schemaType":7,"seo":1647,"stem":1648,"__hash__":1649},"blog\u002Fblog\u002F2025-satellite-imagery-refresh.md","2025 Satellite Imagery Map Refresh",{"type":14,"value":1521,"toc":1635},[1522,1525,1533,1536,1539,1542,1546,1550,1553,1556,1560,1563,1567],[17,1523,1519],{"id":1524},"_2025-satellite-imagery-map-refresh",[24,1526,1527,1528,1532],{},"Today, Stadia Maps unveils the latest update and enhancements to our ",[35,1529,212],{"href":1530,"rel":1531,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Fmaps\u002Fmap-styles\u002Fsatellite-imagery\u002F?utm_source=marketing_site&utm_campaign=2025_satellite_refresh&utm_medium=blog&utm_content=product_reference",[39]," imagery.",[24,1534,1535],{},"This refresh includes expansion of our 30cm data, better mosaicking across multiple resolutions around the globe,\nand refreshes the imagery in our entire map portfolio.",[24,1537,1538],{},"People use imagery maps every day to understand a location in its “true” visual context: hikers verify trails in\nstunning clarity, families find their next home—with a porch and lots of trees for the summer, and travelers plan their\nvacation surroundings in vivid detail.",[24,1540,1541],{},"Our latest enhancements deliver visual context that’s not just updated—but richer, sharper, and more precise, tailored\nfor every application.",[215,1543],{":center":1544,":scroll-zoom":218,":use-search":218,":use-theme-switcher":219,":zoom":1545,"id":221,"style":222,"theme":223},"[172,-43.2]","7",[28,1547,1549],{"id":1548},"higher-definition-and-clarity-for-the-entire-world","Higher Definition and Clarity for the Entire World",[24,1551,1552],{},"Now, with 10x more 30cm resolution imagery available, you can see small objects, structures, and surface details like\nnever before.",[24,1554,1555],{},"We've also expanded our mosaicked data and now offer 20% coverage at 30cm resolution, 54% at 50cm, and full coverage\n(100%) at 1.5m, providing even more seamless imagery for larger geographic areas.",[1205,1557,1559],{"id":1558},"keeping-things-fresh","Keeping Things Fresh",[24,1561,1562],{},"We're dedicated to keeping our imagery as fresh and current as possible.\nOur oldest imagery is now only a couple of years old.\nWe will continue updating pixels all the time, providing you with the freshest, highest quality basemaps possible.",[28,1564,1566],{"id":1565},"next-steps","Next Steps",[56,1568,1569,1599,1606,1612],{},[59,1570,1571,1572,1576,1577],{},"You can get started with our ",[35,1573,212],{"href":1574,"rel":1575,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Fmaps\u002Fmap-styles\u002Fsatellite-imagery\u002F?utm_source=marketing_site&utm_campaign=2025_satellite_refresh&utm_medium=blog&utm_content=next_steps",[39]," imagery basemap today:\n",[56,1578,1579,1582,1591],{},[59,1580,1581],{},"Our latest imagery is already available to Enterprise, Professional, and Standard subscribers.",[59,1583,1584,1585,1590],{},"Current customers not already on our Standard or Professional plans can ",[35,1586,1589],{"href":1587,"rel":1588,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fupgrading-subscription\u002F?utm_source=marketing_site&utm_campaign=2025_satellite_refresh&utm_content=next_steps&utm_medium=blog",[39],"quickly upgrade using our guide","\nto gain access now.",[59,1592,1593,1594,1598],{},"If you aren't already using Stadia Maps, ",[35,1595,1216],{"href":1596,"rel":1597,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=2025_satellite_refresh&utm_content=next_steps",[39]," and get started with a 14-day free trial to our\nProfessional plan.",[59,1600,1601],{},[35,1602,1605],{"href":1603,"rel":1604,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fmap-styles\u002Falidade-satellite\u002F?utm_source=marketing_site&utm_campaign=2025_satellite_refresh&utm_content=get_started_satellite&utm_medium=blog",[39],"Get started in MapLibre, Leaflet, OpenLayers or just about any other mapping library!",[59,1607,1608],{},[35,1609,1611],{"href":1610},"\u002Fexplore-the-map\u002F#style=alidade_satellite","Explore the new imagery",[59,1613,1614,1615,352,1618,437,1623,1056,1626,1629,1630,1634],{},"Follow Stadia Maps on ",[35,1616,1248],{"href":1246,"rel":1617,"target":40},[39],[35,1619,1622],{"href":1620,"rel":1621,"target":40},"https:\u002F\u002Fx.com\u002F@stadiamaps",[39],"Twitter\u002FX",[35,1624,1258],{"href":1256,"rel":1625,"target":40},[39],[35,1627,1264],{"href":1262,"rel":1628,"target":40},[39],", or\nsign-up for our ",[35,1631,1633],{"href":1268,"rel":1632,"target":40},[39],"newsletter"," to hear about exciting developments first.",{"title":168,"searchDepth":169,"depth":169,"links":1636},[1637,1640],{"id":1548,"depth":172,"text":1549,"children":1638},[1639],{"id":1558,"depth":669,"text":1559},{"id":1565,"depth":172,"text":1566},"The 2025 imagery refresh extends 30cm resolution coverage, enhances mosaics at 30cm, 50cm, and 1.5m, and renews imagery throughout our complete map portfolio.",[283,284,285,286,212],{},"\u002Fblog\u002F2025-satellite-imagery-refresh","2025-03-07","---\ndescription: >-\n  The 2025 imagery refresh extends 30cm resolution coverage, enhances mosaics at 30cm, 50cm, and 1.5m, and renews\n  imagery throughout our complete map portfolio.\npublished: 2025-03-07\nkeywords:\n  - Satellite Imagery\n  - Aerial Photography\n  - Map Update\n  - High Resolution\n  - Alidade Satellite\n---\n\n# 2025 Satellite Imagery Map Refresh\n\nToday, Stadia Maps unveils the latest update and enhancements to our [Alidade Satellite](https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Fmaps\u002Fmap-styles\u002Fsatellite-imagery\u002F?utm_source=marketing_site&utm_campaign=2025_satellite_refresh&utm_medium=blog&utm_content=product_reference) imagery.\n\nThis refresh includes expansion of our 30cm data, better mosaicking across multiple resolutions around the globe,\nand refreshes the imagery in our entire map portfolio.\n\nPeople use imagery maps every day to understand a location in its “true” visual context: hikers verify trails in\nstunning clarity, families find their next home—with a porch and lots of trees for the summer, and travelers plan their\nvacation surroundings in vivid detail.\n\nOur latest enhancements deliver visual context that’s not just updated—but richer, sharper, and more precise, tailored\nfor every application.\n\n::cross-platform-map{id=\"map\" style=\"height: 400px;\"}\n---\ncenter: [172, -43.2]\nscroll-zoom: true\nzoom: 7\ntheme: alidade_satellite\nuse-theme-switcher: false\nuse-search: true\n---\n::\n\n## Higher Definition and Clarity for the Entire World\n\nNow, with 10x more 30cm resolution imagery available, you can see small objects, structures, and surface details like\nnever before.\n\nWe've also expanded our mosaicked data and now offer 20% coverage at 30cm resolution, 54% at 50cm, and full coverage\n(100%) at 1.5m, providing even more seamless imagery for larger geographic areas.\n\n### Keeping Things Fresh\n\nWe're dedicated to keeping our imagery as fresh and current as possible.\nOur oldest imagery is now only a couple of years old.\nWe will continue updating pixels all the time, providing you with the freshest, highest quality basemaps possible.\n\n## Next Steps\n\n- You can get started with our [Alidade Satellite](https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002Fmaps\u002Fmap-styles\u002Fsatellite-imagery\u002F?utm_source=marketing_site&utm_campaign=2025_satellite_refresh&utm_medium=blog&utm_content=next_steps) imagery basemap today:\n    - Our latest imagery is already available to Enterprise, Professional, and Standard subscribers.\n    - Current customers not already on our Standard or Professional plans can [quickly upgrade using our guide](https:\u002F\u002Fdocs.stadiamaps.com\u002Fupgrading-subscription\u002F?utm_source=marketing_site&utm_campaign=2025_satellite_refresh&utm_content=next_steps&utm_medium=blog)\n    to gain access now.\n    - If you aren't already using Stadia Maps, [create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=2025_satellite_refresh&utm_content=next_steps) and get started with a 14-day free trial to our\n    Professional plan.\n- [Get started in MapLibre, Leaflet, OpenLayers or just about any other mapping library!](https:\u002F\u002Fdocs.stadiamaps.com\u002Fmap-styles\u002Falidade-satellite\u002F?utm_source=marketing_site&utm_campaign=2025_satellite_refresh&utm_content=get_started_satellite&utm_medium=blog)\n- [Explore the new imagery](\u002Fexplore-the-map\u002F#style=alidade_satellite)\n- Follow Stadia Maps on [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter\u002FX](https:\u002F\u002Fx.com\u002F@stadiamaps),\n  [BlueSky](https:\u002F\u002Fbsky.app\u002Fprofile\u002Fstadiamaps.com) or [LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or\n  sign-up for our [newsletter](https:\u002F\u002Feepurl.com\u002Fgs51fD) to hear about exciting developments first.",{"title":1519,"description":1641},"blog\u002F2025-satellite-imagery-refresh","j53770PIGwxJK4FZnN2VPy_6X4xJz4L7bzmiicES7oI",{"id":1651,"title":1652,"abstract":7,"author":7,"body":1653,"description":1764,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":1765,"meta":1768,"modified":7,"navigation":187,"path":1769,"proficiencyLevel":7,"published":1770,"rawbody":1771,"schemaOrg":7,"schemaType":7,"seo":1772,"stem":1773,"__hash__":1774},"blog\u002Fblog\u002Fgeocoding-foursquare-beta.md","Announcing Foursquare OS Places Beta",{"type":14,"value":1654,"toc":1757},[1655,1658,1661,1665,1668,1681,1685,1688,1692,1695,1698,1700,1708,1712],[17,1656,1652],{"id":1657},"announcing-foursquare-os-places-beta",[24,1659,1660],{},"Our geocoding and autocomplete search APIs provide fast and accurate place-to-coordinate matching.\nStarting today, with our latest geocoding update, we are including even more data, smarter searches, and better localization for our users.",[28,1662,1664],{"id":1663},"millions-of-new-pois-with-foursquare-os-places-data","Millions of new POIs with Foursquare OS Places data",[24,1666,1667],{},"We're excited to introduce Foursquare as a new data source,\nbringing even richer location data and improved search capabilities to all of our geocoding endpoints.\nWith this update, we have unlocked access to millions of new points of interest worldwide,\nmaking it easier for you to find the places you are looking for.",[24,1669,1670,1671,1674,1675,1680],{},"Since we're launching this as beta data source, you'll need to opt in to participate.\nTo opt in, just add ",[349,1672,1673],{},"foursquare"," as a source in your request.\nAnd just like other open data sources, you can submit corrections if you find a mistake\n(we'll pick them up in our next update)!\nCheck out the Foursquare's ",[35,1676,1679],{"href":1677,"rel":1678,"target":40},"https:\u002F\u002Fopensource.foursquare.com\u002Fplacemaker\u002F",[39],"Placemaker program page"," for details.",[28,1682,1684],{"id":1683},"expanded-localization","Expanded Localization",[24,1686,1687],{},"Our geocoding and search APIs can return place names in dozens of languages.\nThis update expands our localized name coverage with more than 250,000 additional place names.\nWhichever language your users speak, they'll see better results.",[28,1689,1691],{"id":1690},"smarter-fuzzy-search-and-interpolation","Smarter Fuzzy Search and Interpolation",[24,1693,1694],{},"We fine-tuned our search capabilities to better handle house numbers with letters (e.g. 13L)\nand varied postal code spacing,\nensuring more accurate matches and prioritized results.",[24,1696,1697],{},"Similarly, we have also enhanced our address interpolation,\nmaking results even more precise when exact house numbers aren't available.",[28,1699,428],{"id":427},[24,1701,1702,1703,1707],{},"All of these improvements are available immediately!\nIf you're using our ",[35,1704,1159],{"href":1705,"rel":1706,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=foursquare_beta_announcement&utm_content=sdk_cta",[39],",\nupdate to the latest version to include the Foursquare source.\nAll other improvements are automatic without any further action.",[28,1709,1711],{"id":1710},"learn-more-next-steps","Learn More & Next Steps",[56,1713,1714,1722,1730,1738],{},[59,1715,1716,1721],{},[35,1717,1720],{"href":1718,"rel":1719,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=foursquare_beta_announcement",[39],"Create an account"," to get an API key. You can start building today without a credit card!",[59,1723,1724,1725,458],{},"Get started today by diving into the details in our ",[35,1726,1729],{"href":1727,"rel":1728,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=foursquare_beta_announcement&utm_content=foursquare_beta_next_steps",[39],"geocoding documentation",[59,1731,1231,1732,1056,1735,1240],{},[35,1733,849],{"href":847,"rel":1734,"target":40},[39],[35,1736,1239],{"href":1237,"rel":1737,"target":40},[39],[59,1739,1243,1740,352,1743,352,1746,1749,1750,1753,1754,1271],{},[35,1741,1248],{"href":1246,"rel":1742,"target":40},[39],[35,1744,1253],{"href":1251,"rel":1745,"target":40},[39],[35,1747,1258],{"href":1256,"rel":1748,"target":40},[39],", or\n",[35,1751,1264],{"href":1262,"rel":1752,"target":40},[39],", or sign-up for our ",[35,1755,1270],{"href":1268,"rel":1756,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":1758},[1759,1760,1761,1762,1763],{"id":1663,"depth":172,"text":1664},{"id":1683,"depth":172,"text":1684},{"id":1690,"depth":172,"text":1691},{"id":427,"depth":172,"text":428},{"id":1710,"depth":172,"text":1711},"Our latest geocoding update includes more data, smarter searches, and better localization.",[402,1290,1766,1508,1767],"POI Data","Location Data",{},"\u002Fblog\u002Fgeocoding-foursquare-beta","2025-02-19","---\ndescription: \"Our latest geocoding update includes more data, smarter searches, and better localization.\"\npublished: \"2025-02-19\"\nkeywords:\n  - Geocoding\n  - Foursquare\n  - POI Data\n  - Place Search\n  - Location Data\n---\n\n# Announcing Foursquare OS Places Beta\n\nOur geocoding and autocomplete search APIs provide fast and accurate place-to-coordinate matching.\nStarting today, with our latest geocoding update, we are including even more data, smarter searches, and better localization for our users.\n\n## Millions of new POIs with Foursquare OS Places data\n\nWe're excited to introduce Foursquare as a new data source,\nbringing even richer location data and improved search capabilities to all of our geocoding endpoints.\nWith this update, we have unlocked access to millions of new points of interest worldwide,\nmaking it easier for you to find the places you are looking for.\n\nSince we're launching this as beta data source, you'll need to opt in to participate.\nTo opt in, just add `foursquare` as a source in your request.\nAnd just like other open data sources, you can submit corrections if you find a mistake\n(we'll pick them up in our next update)!\nCheck out the Foursquare's [Placemaker program page](https:\u002F\u002Fopensource.foursquare.com\u002Fplacemaker\u002F) for details.\n\n## Expanded Localization\n\nOur geocoding and search APIs can return place names in dozens of languages.\nThis update expands our localized name coverage with more than 250,000 additional place names.\nWhichever language your users speak, they'll see better results.\n\n## Smarter Fuzzy Search and Interpolation\n\nWe fine-tuned our search capabilities to better handle house numbers with letters (e.g. 13L)\nand varied postal code spacing,\nensuring more accurate matches and prioritized results.\n\nSimilarly, we have also enhanced our address interpolation,\nmaking results even more precise when exact house numbers aren't available.\n\n## Available Today\n\nAll of these improvements are available immediately!\nIf you're using our [SDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=foursquare_beta_announcement&utm_content=sdk_cta),\nupdate to the latest version to include the Foursquare source.\nAll other improvements are automatic without any further action.\n\n## Learn More & Next Steps\n\n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=foursquare_beta_announcement) to get an API key. You can start building today without a credit card!\n- Get started today by diving into the details in our [geocoding documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=foursquare_beta_announcement&utm_content=foursquare_beta_next_steps).\n- Join our community on [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT) or [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) to share what you're working on or get help.\n- Follow us on [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps), [BlueSky](https:\u002F\u002Fbsky.app\u002Fprofile\u002Fstadiamaps.com), or\n  [LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD) to stay up to date.\n",{"title":1652,"description":1764},"blog\u002Fgeocoding-foursquare-beta","aYTsewoq7h3yORE0zrJ2syd9Hwoufy_bsR-Zsh8cs34",{"id":1776,"title":1777,"abstract":7,"author":7,"body":1778,"description":2586,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":2587,"meta":2593,"modified":7,"navigation":187,"path":2594,"proficiencyLevel":872,"published":2595,"rawbody":2596,"schemaOrg":7,"schemaType":875,"seo":2597,"stem":2598,"__hash__":2599},"blog\u002Fblog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-2.md","Ferrostar: Building a Cross-Platform Navigation SDK in Rust (Part 2 - iOS Packaging)",{"type":14,"value":1779,"toc":2577},[1780,1783,1801,1804,1807,1814,1818,1829,1835,2047,2053,2060,2066,2076,2083,2147,2150,2157,2161,2164,2167,2170,2181,2194,2244,2254,2264,2282,2296,2300,2309,2326,2329,2356,2367,2389,2396,2399,2403,2406,2417,2427,2436,2440,2443,2468,2471,2475,2478,2481,2495,2498,2528,2545,2551,2555,2558,2571,2574],[17,1781,1777],{"id":1782},"ferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-2-ios-packaging",[24,1784,1785,1786,1790,1791,1796,1797,1800],{},"It's been a while since our ",[35,1787,1789],{"href":1788},"\u002Fblog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-1","first deep dive","\ninto the tech behind ",[35,1792,1795],{"href":1793,"rel":1794,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fferrostar\u002F?utm_source=marketing_site&utm_campaign=ferrostar_tech_blog_2&utm_medium=blog",[39],"Ferrostar",", our new turn-by-turn navigation SDK.\nAs a recap, our ",[35,1798,1799],{"href":1788},"last post"," covered why we're writing the core in Rust,\nhow we approached both code and data model sharing,\nand looked at the architecture from a high level.",[24,1802,1803],{},"Writing some code for private use is one thing,\nbut publishing it for others to use can be maddeningly difficult.\nWhen the time came for us to publish Swift Packages,\nwe found something closer to the latter.",[24,1805,1806],{},"In this post, we'll cover the practical details of how we\ncross-compiled the Rust library for iOS,\npackaged it in an XCFramework,\nand published it as a Swift Package.\nThis is the missing manual we wish we had.",[24,1808,1809],{},[1810,1811],"img",{"alt":1812,"src":1813},"A screenshot of Ferrostar navigating on an iPhone","\u002Fimages\u002Fcontent\u002Fferrostar-landscape-screenshot.png",[28,1815,1817],{"id":1816},"swift-packaging","Swift Packaging",[24,1819,1820,1821,1824,1825,1828],{},"Let's start off by looking at the Swift Package structure.\nWe'll need to add ",[611,1822,1823],{},"two"," targets to our ",[349,1826,1827],{},"Package.swift",":\na binary target for the static library,\nand a Swift target for the generated bindings.",[24,1830,1831,1832,1834],{},"Binary targets in Swift Package Manager can be tricky,\nand this complexity makes our ",[349,1833,1827],{}," file a bit unwieldy from the start.",[636,1836,1840],{"className":1837,"code":1838,"language":1839,"meta":168,"style":168},"language-swift shiki shiki-themes github-light","let binaryTarget: Target\nlet useLocalFramework = false  \u002F\u002F NB: Set this to true when developing locally!\n\nif useLocalFramework {\n    binaryTarget = .binaryTarget(\n        name: \"FerrostarCoreRS\",\n        \u002F\u002F IMPORTANT: Swift packages importing this locally will not be able to\n        \u002F\u002F import Ferrostar core unless you specify this as a relative path!\n        path: \".\u002Fcommon\u002Ftarget\u002Fios\u002Flibferrostar-rs.xcframework\"\n    )\n} else {\n    \u002F\u002F Git stuff which we'll come back to at the end.\n    let releaseTag = \"0.23.0\"\n    let releaseChecksum = \"fa308b519db5424d73d00d60ca03fc18c1dcf2f88704aadce29259d12f2de2b2\"\n    binaryTarget = .binaryTarget(\n        name: \"FerrostarCoreRS\",\n        url:\n        \"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar\u002Freleases\u002Fdownload\u002F\\(releaseTag)\u002Flibferrostar-rs.xcframework.zip\",\n        checksum: releaseChecksum\n    )\n}\n","swift",[349,1841,1842,1851,1868,1873,1881,1897,1909,1914,1919,1930,1936,1948,1954,1968,1981,1994,2005,2014,2028,2037,2042],{"__ignoreMap":168},[644,1843,1844,1848],{"class":646,"line":647},[644,1845,1847],{"class":1846},"sD7c4","let",[644,1849,1850],{"class":650}," binaryTarget: Target\n",[644,1852,1853,1855,1858,1861,1864],{"class":646,"line":172},[644,1854,1847],{"class":1846},[644,1856,1857],{"class":650}," useLocalFramework ",[644,1859,1860],{"class":1846},"=",[644,1862,1863],{"class":656}," false",[644,1865,1867],{"class":1866},"sAwPA","  \u002F\u002F NB: Set this to true when developing locally!\n",[644,1869,1870],{"class":646,"line":669},[644,1871,1872],{"emptyLinePlaceholder":187},"\n",[644,1874,1875,1878],{"class":646,"line":169},[644,1876,1877],{"class":1846},"if",[644,1879,1880],{"class":650}," useLocalFramework {\n",[644,1882,1883,1886,1888,1891,1894],{"class":646,"line":692},[644,1884,1885],{"class":650},"    binaryTarget ",[644,1887,1860],{"class":1846},[644,1889,1890],{"class":650}," .",[644,1892,1893],{"class":656},"binaryTarget",[644,1895,1896],{"class":650},"(\n",[644,1898,1899,1902,1904,1907],{"class":646,"line":755},[644,1900,1901],{"class":656},"        name",[644,1903,660],{"class":650},[644,1905,1906],{"class":663},"\"FerrostarCoreRS\"",[644,1908,437],{"class":650},[644,1910,1911],{"class":646,"line":768},[644,1912,1913],{"class":1866},"        \u002F\u002F IMPORTANT: Swift packages importing this locally will not be able to\n",[644,1915,1916],{"class":646,"line":779},[644,1917,1918],{"class":1866},"        \u002F\u002F import Ferrostar core unless you specify this as a relative path!\n",[644,1920,1922,1925,1927],{"class":646,"line":1921},9,[644,1923,1924],{"class":656},"        path",[644,1926,660],{"class":650},[644,1928,1929],{"class":663},"\".\u002Fcommon\u002Ftarget\u002Fios\u002Flibferrostar-rs.xcframework\"\n",[644,1931,1933],{"class":646,"line":1932},10,[644,1934,1935],{"class":650},"    )\n",[644,1937,1939,1942,1945],{"class":646,"line":1938},11,[644,1940,1941],{"class":650},"} ",[644,1943,1944],{"class":1846},"else",[644,1946,1947],{"class":650}," {\n",[644,1949,1951],{"class":646,"line":1950},12,[644,1952,1953],{"class":1866},"    \u002F\u002F Git stuff which we'll come back to at the end.\n",[644,1955,1957,1960,1963,1965],{"class":646,"line":1956},13,[644,1958,1959],{"class":1846},"    let",[644,1961,1962],{"class":650}," releaseTag ",[644,1964,1860],{"class":1846},[644,1966,1967],{"class":663}," \"0.23.0\"\n",[644,1969,1971,1973,1976,1978],{"class":646,"line":1970},14,[644,1972,1959],{"class":1846},[644,1974,1975],{"class":650}," releaseChecksum ",[644,1977,1860],{"class":1846},[644,1979,1980],{"class":663}," \"fa308b519db5424d73d00d60ca03fc18c1dcf2f88704aadce29259d12f2de2b2\"\n",[644,1982,1984,1986,1988,1990,1992],{"class":646,"line":1983},15,[644,1985,1885],{"class":650},[644,1987,1860],{"class":1846},[644,1989,1890],{"class":650},[644,1991,1893],{"class":656},[644,1993,1896],{"class":650},[644,1995,1997,1999,2001,2003],{"class":646,"line":1996},16,[644,1998,1901],{"class":656},[644,2000,660],{"class":650},[644,2002,1906],{"class":663},[644,2004,437],{"class":650},[644,2006,2008,2011],{"class":646,"line":2007},17,[644,2009,2010],{"class":656},"        url",[644,2012,2013],{"class":650},":\n",[644,2015,2017,2020,2023,2026],{"class":646,"line":2016},18,[644,2018,2019],{"class":663},"        \"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar\u002Freleases\u002Fdownload\u002F",[644,2021,2022],{"class":663},"\\(releaseTag)",[644,2024,2025],{"class":663},"\u002Flibferrostar-rs.xcframework.zip\"",[644,2027,437],{"class":650},[644,2029,2031,2034],{"class":646,"line":2030},19,[644,2032,2033],{"class":656},"        checksum",[644,2035,2036],{"class":650},": releaseChecksum\n",[644,2038,2040],{"class":646,"line":2039},20,[644,2041,1935],{"class":650},[644,2043,2045],{"class":646,"line":2044},21,[644,2046,695],{"class":650},[24,2048,2049,2050,2052],{},"Unfortunately, we haven't found a way to use the same ",[349,2051,1827],{},"\nunmodified for both local development within the \"project\" and for publishing.\n(To be fair, this is an extremely rare feature,\nbut it's worth noting that Cargo workspaces let you do this seamlessly with Rust crates.)\nSo, we need to add some switching logic to our package definition.",[24,2054,2055,2056,2059],{},"The above is the solution we came up with.\nWe always ensure that ",[349,2057,2058],{},"useLocalFramework = false"," for the version checked in to git.\nPublished versions will need to point to the released artifact,\nor else we'd require every developer to check out and build the whole project locally.",[24,2061,2062,2063,2065],{},"For local development and CI builds,\nwhere you may need unreleased changes in the Rust core,\nyou have to override the value to ",[349,2064,218],{},".\nIf anyone knows a cleaner solution to this, let us know!",[24,2067,2068,2069,2072,2073,2075],{},"Another complicating detail is that you ",[611,2070,2071],{},"need"," a checksum for remote binary downloads.\nThis is a safety measure built into the Swift Package Manager\nto prevent supply chain attacks.\nSince the checksum can't be known until build time,\nwe have CI rewrite this line in ",[349,2074,1827],{}," when publishing a release.\n(We'll cover this dance later.)",[24,2077,2078,2079,2082],{},"One target down... the other is fortunately a bit simpler.\nWe've called this ",[349,2080,2081],{},"FerrostarCoreFFI"," in our project,\nto make the distinction clear between the FFI bindings and the Rust binary.",[636,2084,2086],{"className":1837,"code":2085,"language":1839,"meta":168,"style":168},".target(\n    name: \"FerrostarCoreFFI\",\n    dependencies: [.target(name: \"FerrostarCoreRS\")],\n    path: \"apple\u002FSources\u002FUniFFI\"\n)\n",[349,2087,2088,2097,2109,2132,2142],{"__ignoreMap":168},[644,2089,2090,2092,2095],{"class":646,"line":647},[644,2091,458],{"class":650},[644,2093,2094],{"class":656},"target",[644,2096,1896],{"class":650},[644,2098,2099,2102,2104,2107],{"class":646,"line":172},[644,2100,2101],{"class":656},"    name",[644,2103,660],{"class":650},[644,2105,2106],{"class":663},"\"FerrostarCoreFFI\"",[644,2108,437],{"class":650},[644,2110,2111,2114,2117,2119,2122,2125,2127,2129],{"class":646,"line":669},[644,2112,2113],{"class":656},"    dependencies",[644,2115,2116],{"class":650},": [.",[644,2118,2094],{"class":656},[644,2120,2121],{"class":650},"(",[644,2123,2124],{"class":656},"name",[644,2126,660],{"class":650},[644,2128,1906],{"class":663},[644,2130,2131],{"class":650},")],\n",[644,2133,2134,2137,2139],{"class":646,"line":169},[644,2135,2136],{"class":656},"    path",[644,2138,660],{"class":650},[644,2140,2141],{"class":663},"\"apple\u002FSources\u002FUniFFI\"\n",[644,2143,2144],{"class":646,"line":692},[644,2145,2146],{"class":650},")\n",[24,2148,2149],{},"This is pure Swift and doesn't have any surprises.\nIt just depends on the binary target,\nand includes a source directory which will contain the generated bindings.",[24,2151,2152,2153,2156],{},"You'll need to add both the source and binary target to your list of ",[349,2154,2155],{},"targets",".\nYou can now reference them by name from any of your other targets,\nand\u002For publish them via products.",[28,2158,2160],{"id":2159},"cross-compilation","Cross compilation",[24,2162,2163],{},"Now that we've looked at the package structure,\nlet's see what actually goes into the two targets.",[24,2165,2166],{},"We'll tackle cross compilation first.\nWe're going to compile the Rust code for all the relevant iOS target architectures,\njust like Xcode does for our Swift projects.",[24,2168,2169],{},"Cross compilation is quite tricky (maybe even traumatic) in some languages,\nbut Cargo is full of pleasant surprises.",[636,2171,2175],{"className":2172,"code":2173,"language":2174,"meta":168,"style":168},"language-shell shiki shiki-themes github-light","cargo build --lib --release --target some-target-triple\n","shell",[349,2176,2177],{"__ignoreMap":168},[644,2178,2179],{"class":646,"line":647},[644,2180,2173],{},[24,2182,2183,2184,2189,2190,2193],{},"That's it!\nJust specify the ",[35,2185,2188],{"href":2186,"rel":2187,"target":40},"https:\u002F\u002Fdoc.rust-lang.org\u002Fnightly\u002Frustc\u002Fplatform-support.html",[39],"target triple","!\nFor iOS, we actually need to compile for ",[611,2191,2192],{},"three"," targets:",[2195,2196,2197,2210],"table",{},[2198,2199,2200],"thead",{},[2201,2202,2203,2207],"tr",{},[2204,2205,2206],"th",{},"Target triple",[2204,2208,2209],{},"Description",[2211,2212,2213,2224,2234],"tbody",{},[2201,2214,2215,2221],{},[2216,2217,2218],"td",{},[349,2219,2220],{},"x86_64-apple-ios",[2216,2222,2223],{},"Simulator for Intel-based Macs",[2201,2225,2226,2231],{},[2216,2227,2228],{},[349,2229,2230],{},"aarch64-apple-ios-sim",[2216,2232,2233],{},"Simulator for ARM-based Macs",[2201,2235,2236,2241],{},[2216,2237,2238],{},[349,2239,2240],{},"aarch64-apple-ios",[2216,2242,2243],{},"iOS devices",[24,2245,2246,2247,2250,2251,458],{},"If you try running this on your machine right now,\nyou may get an error since you need to have the target toolchain installed.\nFortunately, this is easy.\nIf you're using ",[349,2248,2249],{},"rustup",", you can add any target with the command\n",[349,2252,2253],{},"rustup target add your-target-triple",[24,2255,2256,2257,458],{},"For iOS, there are just three targets,\nbut we'll have a LOT more by the time we're done with this series.\nRemembering all of these is a lot of work,\nbut there's a relatively under-appreciated file that can help us out:\n",[35,2258,2261],{"href":2259,"rel":2260,"target":40},"https:\u002F\u002Frust-lang.github.io\u002Frustup\u002Foverrides.html#the-toolchain-file",[39],[349,2262,2263],{},"rust-toolchain.toml",[24,2265,2266,2267,2269,2270,2273,2274,458],{},"If you're using ",[349,2268,2249],{}," to install ",[349,2271,2272],{},"cargo",",\nit will automatically install the relevant toolchains for you!\nWe can check this into git and call it a day.\nHere's ",[35,2275,2278,2279,2281],{"href":2276,"rel":2277,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar\u002Fblob\u002Fmain\u002Fcommon\u002Frust-toolchain.toml",[39],"the full ",[349,2280,2263],{}," for Ferrostar",[24,2283,2284,2285,2287,2288,2295],{},"While this file is specifically designed for use with ",[349,2286,2249],{},",\nother build systems often have a way of consuming it too.\nFor example, Nix users could leverage ",[35,2289,2292],{"href":2290,"rel":2291,"target":40},"https:\u002F\u002Fgithub.com\u002Fnix-community\u002Ffenix",[39],[349,2293,2294],{},"fenix.fromToolchainFile","\nto get the same effect.",[28,2297,2299],{"id":2298},"generating-the-ffi-bindings","Generating the FFI Bindings",[24,2301,2302,2303,2308],{},"Now that we have the static library built in its first form,\nwe need an easy way for Swift to interface with it.\nIt's ",[35,2304,2307],{"href":2305,"rel":2306,"target":40},"https:\u002F\u002Fgithub.com\u002Fmozilla\u002Funiffi-rs",[39],"UniFFI","'s time to shine!",[24,2310,2311,2312,2315,2316,2319,2320,2325],{},"Since our ",[35,2313,2314],{"href":1788},"first post",", UniFFI has evolved a ",[349,2317,2318],{},"uniffi-bindgen-swift"," crate concept\nwith a slightly different CLI.\nNot a lot has changed, but it's worth a quick note in case you're on an older version.\nIf you're starting fresh, this ",[35,2321,2324],{"href":2322,"rel":2323,"target":40},"https:\u002F\u002Fgithub.com\u002Fianthetechie\u002Funiffi-starter",[39],"starter template","\nhas everything ready to go with the new setup.",[24,2327,2328],{},"Here's how we generate the bindings:",[107,2330,2331,2340,2350],{},[59,2332,2333,2334,2336,2337,458],{},"Run ",[349,2335,2318],{}," via ",[349,2338,2339],{},"cargo run -p",[59,2341,2342,2343,2346,2347,2349],{},"Copy the ",[611,2344,2345],{},"generated Swift file"," to the appropriate source directory (the ",[349,2348,2081],{}," target's source path in our example).",[59,2351,2342,2352,2355],{},[611,2353,2354],{},"clang module map"," into a framework staging directory.",[24,2357,2358,2359,2362,2363,2366],{},"Here's the relevant portion of our build script,\nwhere ",[349,2360,2361],{},"$1"," is the name of the library (",[349,2364,2365],{},"ferrostar"," in our case).",[636,2368,2372],{"className":2369,"code":2370,"language":2371,"meta":168,"style":168},"language-zsh shiki shiki-themes github-light","cargo run -p uniffi-bindgen-swift -- target\u002Faarch64-apple-ios\u002Frelease\u002Flib$1.a target\u002Funiffi-xcframework-staging --swift-sources --headers --modulemap --module-name $1FFI --modulemap-filename module.modulemap\nmv target\u002Funiffi-xcframework-staging\u002F*.swift ..\u002Fapple\u002FSources\u002FUniFFI\u002F\nmv target\u002Funiffi-xcframework-staging\u002Fmodule.modulemap target\u002Funiffi-xcframework-staging\u002Fmodule.modulemap\n","zsh",[349,2373,2374,2379,2384],{"__ignoreMap":168},[644,2375,2376],{"class":646,"line":647},[644,2377,2378],{},"cargo run -p uniffi-bindgen-swift -- target\u002Faarch64-apple-ios\u002Frelease\u002Flib$1.a target\u002Funiffi-xcframework-staging --swift-sources --headers --modulemap --module-name $1FFI --modulemap-filename module.modulemap\n",[644,2380,2381],{"class":646,"line":172},[644,2382,2383],{},"mv target\u002Funiffi-xcframework-staging\u002F*.swift ..\u002Fapple\u002FSources\u002FUniFFI\u002F\n",[644,2385,2386],{"class":646,"line":669},[644,2387,2388],{},"mv target\u002Funiffi-xcframework-staging\u002Fmodule.modulemap target\u002Funiffi-xcframework-staging\u002Fmodule.modulemap\n",[24,2390,2391,2393,2394,458],{},[349,2392,2318],{}," looks at the static library\nand generates everything we need to smoothly interact with it from Swift.\nThis includes enums, protocols, library loading code, etc.;\nthis is where it does the magic that makes the Rust library feel like a native Swift package.\nWe just need to copy everything into the location we said in our ",[349,2395,1827],{},[24,2397,2398],{},"NOTE: It is possible to integrate these steps into Xcode.\nHowever, given the relative difficulty of doing this\nand the overall flakiness of the Xcode build process,\nwe opted for a simple, reliable shell script.\nThis does mean you need to manually rebuild when changing Rust files,\nbut that's a small step.",[28,2400,2402],{"id":2401},"building-a-fat-library-universal-binary","Building a \"fat\" library (universal binary)",[24,2404,2405],{},"As a last step before creating the XCFramework,\nwe need to do something a bit funny and fuse two of our three binary targets together.",[24,2407,2408,2409,2412,2413,2416],{},"The way that XCFramework is designed,\nit expects a single binary for each ",[611,2410,2411],{},"platform",", not each ",[611,2414,2415],{},"CPU architecture",".\nAnd we have two binaries for the iOS Simulator platform:\none for the newer Apple Silicon and one for Intel.",[24,2418,2419,2420,2422,2423,2426],{},"To get down to one binary per ",[611,2421,2411],{}," (simulator and device),\nwe'll use an old tool, ",[349,2424,2425],{},"lipo"," to generate a \"fat\" binary with both architectures\nin a single file.",[636,2428,2430],{"className":2369,"code":2429,"language":2371,"meta":168,"style":168},"lipo -create target\u002Fx86_64-apple-ios\u002Frelease\u002Flib$1.a target\u002Faarch64-apple-ios-sim\u002Frelease\u002Flib$1.a -output target\u002Fios-simulator-fat\u002Frelease\u002Flib$1.a\n",[349,2431,2432],{"__ignoreMap":168},[644,2433,2434],{"class":646,"line":647},[644,2435,2429],{},[28,2437,2439],{"id":2438},"generating-the-xcframework","Generating the XCFramework",[24,2441,2442],{},"Now we finally put all of this together in an XCFramework.\nSome teams actually do this by hand,\nsince it's a relatively simple structure,\nbut we'll stick to Apple's official tooling.",[636,2444,2446],{"className":2369,"code":2445,"language":2371,"meta":168,"style":168},"xcodebuild -create-xcframework \\\n    -library target\u002Faarch64-apple-ios\u002Frelease\u002Flib$1.a -headers target\u002Funiffi-xcframework-staging \\\n    -library target\u002Fios-simulator-fat\u002Frelease\u002Flib$1.a -headers target\u002Funiffi-xcframework-staging \\\n    -output target\u002Fios\u002Flib$1-rs.xcframework\n",[349,2447,2448,2453,2458,2463],{"__ignoreMap":168},[644,2449,2450],{"class":646,"line":647},[644,2451,2452],{},"xcodebuild -create-xcframework \\\n",[644,2454,2455],{"class":646,"line":172},[644,2456,2457],{},"    -library target\u002Faarch64-apple-ios\u002Frelease\u002Flib$1.a -headers target\u002Funiffi-xcframework-staging \\\n",[644,2459,2460],{"class":646,"line":669},[644,2461,2462],{},"    -library target\u002Fios-simulator-fat\u002Frelease\u002Flib$1.a -headers target\u002Funiffi-xcframework-staging \\\n",[644,2464,2465],{"class":646,"line":169},[644,2466,2467],{},"    -output target\u002Fios\u002Flib$1-rs.xcframework\n",[24,2469,2470],{},"This command combines the two static libraries, header, and module map\ninto a single directory.\nAnd if all went well, we now have a working Swift package that you can test locally!",[28,2472,2474],{"id":2473},"distributing-the-xcframework","Distributing the XCFramework",[24,2476,2477],{},"Now it's time to revisit the git and checksum dance that we glossed over at the start.",[24,2479,2480],{},"Here's our distribution checklist:",[107,2482,2483,2486,2489],{},[59,2484,2485],{},"Zip up the folder.",[59,2487,2488],{},"Compute a checksum for the archive.",[59,2490,2491,2492,2494],{},"Update ",[349,2493,1827],{}," with your release tag and checksum.",[24,2496,2497],{},"We script this in our CI actions like so:",[636,2499,2501],{"className":2369,"code":2500,"language":2371,"meta":168,"style":168},"ditto -c -k --sequesterRsrc --keepParent target\u002Fios\u002Flib$1-rs.xcframework target\u002Fios\u002Flib$1-rs.xcframework.zip\nchecksum=$(swift package compute-checksum target\u002Fios\u002Flib$1-rs.xcframework.zip)\nversion=$(cargo metadata --format-version 1 | jq -r --arg pkg_name \"$1\" '.packages[] | select(.name==$pkg_name) .version')\nsed -i \"\" -E \"s\u002F(let releaseTag = \\\")[^\\\"]+(\\\")\u002F\\1$version\\2\u002Fg\" ..\u002FPackage.swift\nsed -i \"\" -E \"s\u002F(let releaseChecksum = \\\")[^\\\"]+(\\\")\u002F\\1$checksum\\2\u002Fg\" ..\u002FPackage.swift\n",[349,2502,2503,2508,2513,2518,2523],{"__ignoreMap":168},[644,2504,2505],{"class":646,"line":647},[644,2506,2507],{},"ditto -c -k --sequesterRsrc --keepParent target\u002Fios\u002Flib$1-rs.xcframework target\u002Fios\u002Flib$1-rs.xcframework.zip\n",[644,2509,2510],{"class":646,"line":172},[644,2511,2512],{},"checksum=$(swift package compute-checksum target\u002Fios\u002Flib$1-rs.xcframework.zip)\n",[644,2514,2515],{"class":646,"line":669},[644,2516,2517],{},"version=$(cargo metadata --format-version 1 | jq -r --arg pkg_name \"$1\" '.packages[] | select(.name==$pkg_name) .version')\n",[644,2519,2520],{"class":646,"line":169},[644,2521,2522],{},"sed -i \"\" -E \"s\u002F(let releaseTag = \\\")[^\\\"]+(\\\")\u002F\\1$version\\2\u002Fg\" ..\u002FPackage.swift\n",[644,2524,2525],{"class":646,"line":692},[644,2526,2527],{},"sed -i \"\" -E \"s\u002F(let releaseChecksum = \\\")[^\\\"]+(\\\")\u002F\\1$checksum\\2\u002Fg\" ..\u002FPackage.swift\n",[24,2529,2530,2533,2534,2537,2538,2540,2541,2544],{},[349,2531,2532],{},"ditto"," is an archiving utility found on all macOS systems.\nWe use this to create the ZIP archive.\nThen, we compute the checksum using ",[349,2535,2536],{},"swift package compute-checksum",".\nThis utility is included in the Xcode Command-line Tools.\nFor versioning, our repository prefers to keep all platforms in sync,\nand derives all versions from the Rust project using a bit of CLI magic.\nTo update ",[349,2539,1827],{},", we use trusty old ",[349,2542,2543],{},"sed"," to rewrite the relevant lines in-place.",[24,2546,2547,2548,2550],{},"For your package to be usable by others,\nyou'll need to host your XCFramework for download somewhere and update ",[349,2549,1827],{},"\nwith an archive checksum and git tag.\nWe use GitHub's release artifact hosting since it's easy and free,\nbut you can also self-host the archive.",[28,2552,2554],{"id":2553},"wrap-up","Wrap-up",[24,2556,2557],{},"Packaging a binary framework for iOS isn't easy,\nand the best practices have evolved in the last few years.\nWhich is probably why no comprehensive (modern) guide exists for our use case!\nWe hope this helps anyone else shipping binary frameworks on iOS.\nWe've been using this process for about a year and a half for Ferrostar,\nand have automated all the steps with shell scripts and CI workflows.",[24,2559,2560,2561,2565,2566,458],{},"If you're curious to try this in your own project,\ncheck out the ",[35,2562,2564],{"href":2322,"rel":2563,"target":40},[39],"UniFFI starter",",\nwhich includes ready-to-go build scripts and all the rest of the project boilerplate.\nAnd for a \"real-world\" CI pipeline on GitHub Actions,\ncheck out the ",[35,2567,2570],{"href":2568,"rel":2569,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar\u002Fblob\u002Fmain\u002F.github\u002Fworkflows\u002Fios-release.yml",[39],"iOS Release action for Ferrostar",[24,2572,2573],{},"In the next installment, we'll cover the build process and packaging for Android.\nGive us a follow on social media, join our Slack or Discord communities,\nor subscribe to our mailing list to get the news first!",[852,2575,2576],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}",{"title":168,"searchDepth":169,"depth":169,"links":2578},[2579,2580,2581,2582,2583,2584,2585],{"id":1816,"depth":172,"text":1817},{"id":2159,"depth":172,"text":2160},{"id":2298,"depth":172,"text":2299},{"id":2401,"depth":172,"text":2402},{"id":2438,"depth":172,"text":2439},{"id":2473,"depth":172,"text":2474},{"id":2553,"depth":172,"text":2554},"A deep dive into building and packaging a cross-platform navigation SDK for iOS.",[2588,2589,2590,2591,2592,1795],"Rust","iOS Development","Swift Package","XCFramework","Cross-Platform Development",{},"\u002Fblog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-2","2024-12-03","---\ndescription: \"A deep dive into building and packaging a cross-platform navigation SDK for iOS.\"\npublished: \"2024-12-03\"\nkeywords:\n  - Rust\n  - iOS Development\n  - Swift Package\n  - XCFramework\n  - Cross-Platform Development\n  - Ferrostar\nschemaType: TechArticle\nproficiencyLevel: Expert\n---\n\n# Ferrostar: Building a Cross-Platform Navigation SDK in Rust (Part 2 - iOS Packaging)\n\nIt's been a while since our [first deep dive](\u002Fblog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-1)\ninto the tech behind [Ferrostar](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fferrostar\u002F?utm_source=marketing_site&utm_campaign=ferrostar_tech_blog_2&utm_medium=blog), our new turn-by-turn navigation SDK.\nAs a recap, our [last post](\u002Fblog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-1) covered why we're writing the core in Rust,\nhow we approached both code and data model sharing,\nand looked at the architecture from a high level.\n\nWriting some code for private use is one thing,\nbut publishing it for others to use can be maddeningly difficult.\nWhen the time came for us to publish Swift Packages,\nwe found something closer to the latter.\n\nIn this post, we'll cover the practical details of how we\ncross-compiled the Rust library for iOS,\npackaged it in an XCFramework,\nand published it as a Swift Package.\nThis is the missing manual we wish we had.\n\n![A screenshot of Ferrostar navigating on an iPhone](\u002Fimages\u002Fcontent\u002Fferrostar-landscape-screenshot.png)\n\n## Swift Packaging\n\nLet's start off by looking at the Swift Package structure.\nWe'll need to add _two_ targets to our `Package.swift`:\na binary target for the static library,\nand a Swift target for the generated bindings.\n\nBinary targets in Swift Package Manager can be tricky,\nand this complexity makes our `Package.swift` file a bit unwieldy from the start.\n\n```swift\nlet binaryTarget: Target\nlet useLocalFramework = false  \u002F\u002F NB: Set this to true when developing locally!\n\nif useLocalFramework {\n    binaryTarget = .binaryTarget(\n        name: \"FerrostarCoreRS\",\n        \u002F\u002F IMPORTANT: Swift packages importing this locally will not be able to\n        \u002F\u002F import Ferrostar core unless you specify this as a relative path!\n        path: \".\u002Fcommon\u002Ftarget\u002Fios\u002Flibferrostar-rs.xcframework\"\n    )\n} else {\n    \u002F\u002F Git stuff which we'll come back to at the end.\n    let releaseTag = \"0.23.0\"\n    let releaseChecksum = \"fa308b519db5424d73d00d60ca03fc18c1dcf2f88704aadce29259d12f2de2b2\"\n    binaryTarget = .binaryTarget(\n        name: \"FerrostarCoreRS\",\n        url:\n        \"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar\u002Freleases\u002Fdownload\u002F\\(releaseTag)\u002Flibferrostar-rs.xcframework.zip\",\n        checksum: releaseChecksum\n    )\n}\n```\n\nUnfortunately, we haven't found a way to use the same `Package.swift`\nunmodified for both local development within the \"project\" and for publishing.\n(To be fair, this is an extremely rare feature,\nbut it's worth noting that Cargo workspaces let you do this seamlessly with Rust crates.)\nSo, we need to add some switching logic to our package definition.\n\nThe above is the solution we came up with.\nWe always ensure that `useLocalFramework = false` for the version checked in to git.\nPublished versions will need to point to the released artifact,\nor else we'd require every developer to check out and build the whole project locally.\n\nFor local development and CI builds,\nwhere you may need unreleased changes in the Rust core,\nyou have to override the value to `true`.\nIf anyone knows a cleaner solution to this, let us know!\n\nAnother complicating detail is that you _need_ a checksum for remote binary downloads.\nThis is a safety measure built into the Swift Package Manager\nto prevent supply chain attacks.\nSince the checksum can't be known until build time,\nwe have CI rewrite this line in `Package.swift` when publishing a release.\n(We'll cover this dance later.)\n\nOne target down... the other is fortunately a bit simpler.\nWe've called this `FerrostarCoreFFI` in our project,\nto make the distinction clear between the FFI bindings and the Rust binary.\n\n```swift\n.target(\n    name: \"FerrostarCoreFFI\",\n    dependencies: [.target(name: \"FerrostarCoreRS\")],\n    path: \"apple\u002FSources\u002FUniFFI\"\n)\n```\n\nThis is pure Swift and doesn't have any surprises.\nIt just depends on the binary target,\nand includes a source directory which will contain the generated bindings.\n\nYou'll need to add both the source and binary target to your list of `targets`.\nYou can now reference them by name from any of your other targets,\nand\u002For publish them via products.\n\n## Cross compilation\n\nNow that we've looked at the package structure,\nlet's see what actually goes into the two targets.\n\nWe'll tackle cross compilation first.\nWe're going to compile the Rust code for all the relevant iOS target architectures,\njust like Xcode does for our Swift projects.\n\nCross compilation is quite tricky (maybe even traumatic) in some languages,\nbut Cargo is full of pleasant surprises.\n\n```shell\ncargo build --lib --release --target some-target-triple\n```\n\nThat's it!\nJust specify the [target triple](https:\u002F\u002Fdoc.rust-lang.org\u002Fnightly\u002Frustc\u002Fplatform-support.html)!\nFor iOS, we actually need to compile for _three_ targets:\n\n| Target triple           | Description                    |\n|-------------------------|--------------------------------|\n| `x86_64-apple-ios`      | Simulator for Intel-based Macs |\n| `aarch64-apple-ios-sim` | Simulator for ARM-based Macs   |\n| `aarch64-apple-ios`     | iOS devices                    |\n\nIf you try running this on your machine right now,\nyou may get an error since you need to have the target toolchain installed.\nFortunately, this is easy.\nIf you're using `rustup`, you can add any target with the command\n`rustup target add your-target-triple`.\n\nFor iOS, there are just three targets,\nbut we'll have a LOT more by the time we're done with this series.\nRemembering all of these is a lot of work,\nbut there's a relatively under-appreciated file that can help us out:\n[`rust-toolchain.toml`](https:\u002F\u002Frust-lang.github.io\u002Frustup\u002Foverrides.html#the-toolchain-file).\n\nIf you're using `rustup` to install `cargo`,\nit will automatically install the relevant toolchains for you!\nWe can check this into git and call it a day.\nHere's [the full `rust-toolchain.toml` for Ferrostar](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar\u002Fblob\u002Fmain\u002Fcommon\u002Frust-toolchain.toml).\n\nWhile this file is specifically designed for use with `rustup`,\nother build systems often have a way of consuming it too.\nFor example, Nix users could leverage [`fenix.fromToolchainFile`](https:\u002F\u002Fgithub.com\u002Fnix-community\u002Ffenix)\nto get the same effect.\n\n## Generating the FFI Bindings\n\nNow that we have the static library built in its first form,\nwe need an easy way for Swift to interface with it.\nIt's [UniFFI](https:\u002F\u002Fgithub.com\u002Fmozilla\u002Funiffi-rs)'s time to shine!\n\nSince our [first post](\u002Fblog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-1), UniFFI has evolved a `uniffi-bindgen-swift` crate concept\nwith a slightly different CLI.\nNot a lot has changed, but it's worth a quick note in case you're on an older version.\nIf you're starting fresh, this [starter template](https:\u002F\u002Fgithub.com\u002Fianthetechie\u002Funiffi-starter)\nhas everything ready to go with the new setup.\n\nHere's how we generate the bindings:\n\n1. Run `uniffi-bindgen-swift` via `cargo run -p`.\n2. Copy the _generated Swift file_ to the appropriate source directory (the `FerrostarCoreFFI` target's source path in our example).\n3. Copy the _clang module map_ into a framework staging directory.\n\nHere's the relevant portion of our build script,\nwhere `$1` is the name of the library (`ferrostar` in our case).\n\n```zsh\ncargo run -p uniffi-bindgen-swift -- target\u002Faarch64-apple-ios\u002Frelease\u002Flib$1.a target\u002Funiffi-xcframework-staging --swift-sources --headers --modulemap --module-name $1FFI --modulemap-filename module.modulemap\nmv target\u002Funiffi-xcframework-staging\u002F*.swift ..\u002Fapple\u002FSources\u002FUniFFI\u002F\nmv target\u002Funiffi-xcframework-staging\u002Fmodule.modulemap target\u002Funiffi-xcframework-staging\u002Fmodule.modulemap\n```\n\n`uniffi-bindgen-swift` looks at the static library\nand generates everything we need to smoothly interact with it from Swift.\nThis includes enums, protocols, library loading code, etc.;\nthis is where it does the magic that makes the Rust library feel like a native Swift package.\nWe just need to copy everything into the location we said in our `Package.swift`.\n\nNOTE: It is possible to integrate these steps into Xcode.\nHowever, given the relative difficulty of doing this\nand the overall flakiness of the Xcode build process,\nwe opted for a simple, reliable shell script.\nThis does mean you need to manually rebuild when changing Rust files,\nbut that's a small step.\n\n## Building a \"fat\" library (universal binary)\n\nAs a last step before creating the XCFramework,\nwe need to do something a bit funny and fuse two of our three binary targets together.\n\nThe way that XCFramework is designed,\nit expects a single binary for each _platform_, not each _CPU architecture_.\nAnd we have two binaries for the iOS Simulator platform:\none for the newer Apple Silicon and one for Intel.\n\nTo get down to one binary per _platform_ (simulator and device),\nwe'll use an old tool, `lipo` to generate a \"fat\" binary with both architectures\nin a single file.\n\n```zsh\nlipo -create target\u002Fx86_64-apple-ios\u002Frelease\u002Flib$1.a target\u002Faarch64-apple-ios-sim\u002Frelease\u002Flib$1.a -output target\u002Fios-simulator-fat\u002Frelease\u002Flib$1.a\n```\n\n## Generating the XCFramework\n\nNow we finally put all of this together in an XCFramework.\nSome teams actually do this by hand,\nsince it's a relatively simple structure,\nbut we'll stick to Apple's official tooling.\n\n```zsh\nxcodebuild -create-xcframework \\\n    -library target\u002Faarch64-apple-ios\u002Frelease\u002Flib$1.a -headers target\u002Funiffi-xcframework-staging \\\n    -library target\u002Fios-simulator-fat\u002Frelease\u002Flib$1.a -headers target\u002Funiffi-xcframework-staging \\\n    -output target\u002Fios\u002Flib$1-rs.xcframework\n```\n\nThis command combines the two static libraries, header, and module map\ninto a single directory.\nAnd if all went well, we now have a working Swift package that you can test locally!\n\n## Distributing the XCFramework\n\nNow it's time to revisit the git and checksum dance that we glossed over at the start.\n\nHere's our distribution checklist:\n\n1. Zip up the folder.\n2. Compute a checksum for the archive.\n3. Update `Package.swift` with your release tag and checksum.\n\nWe script this in our CI actions like so:\n\n```zsh\nditto -c -k --sequesterRsrc --keepParent target\u002Fios\u002Flib$1-rs.xcframework target\u002Fios\u002Flib$1-rs.xcframework.zip\nchecksum=$(swift package compute-checksum target\u002Fios\u002Flib$1-rs.xcframework.zip)\nversion=$(cargo metadata --format-version 1 | jq -r --arg pkg_name \"$1\" '.packages[] | select(.name==$pkg_name) .version')\nsed -i \"\" -E \"s\u002F(let releaseTag = \\\")[^\\\"]+(\\\")\u002F\\1$version\\2\u002Fg\" ..\u002FPackage.swift\nsed -i \"\" -E \"s\u002F(let releaseChecksum = \\\")[^\\\"]+(\\\")\u002F\\1$checksum\\2\u002Fg\" ..\u002FPackage.swift\n```\n\n`ditto` is an archiving utility found on all macOS systems.\nWe use this to create the ZIP archive.\nThen, we compute the checksum using `swift package compute-checksum`.\nThis utility is included in the Xcode Command-line Tools.\nFor versioning, our repository prefers to keep all platforms in sync,\nand derives all versions from the Rust project using a bit of CLI magic.\nTo update `Package.swift`, we use trusty old `sed` to rewrite the relevant lines in-place.\n\nFor your package to be usable by others,\nyou'll need to host your XCFramework for download somewhere and update `Package.swift`\nwith an archive checksum and git tag.\nWe use GitHub's release artifact hosting since it's easy and free,\nbut you can also self-host the archive.\n\n## Wrap-up\n\nPackaging a binary framework for iOS isn't easy,\nand the best practices have evolved in the last few years.\nWhich is probably why no comprehensive (modern) guide exists for our use case!\nWe hope this helps anyone else shipping binary frameworks on iOS.\nWe've been using this process for about a year and a half for Ferrostar,\nand have automated all the steps with shell scripts and CI workflows.\n\nIf you're curious to try this in your own project,\ncheck out the [UniFFI starter](https:\u002F\u002Fgithub.com\u002Fianthetechie\u002Funiffi-starter),\nwhich includes ready-to-go build scripts and all the rest of the project boilerplate.\nAnd for a \"real-world\" CI pipeline on GitHub Actions,\ncheck out the [iOS Release action for Ferrostar](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar\u002Fblob\u002Fmain\u002F.github\u002Fworkflows\u002Fios-release.yml).\n\nIn the next installment, we'll cover the build process and packaging for Android.\nGive us a follow on social media, join our Slack or Discord communities,\nor subscribe to our mailing list to get the news first!\n",{"title":1777,"description":2586},"blog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-2","f0rjv0OjtbYLOvAniwhV2Cod5JvY7CmqkoYHKFUCUiE",{"id":2601,"title":2602,"abstract":7,"author":7,"body":2603,"description":2712,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":2713,"meta":2717,"modified":7,"navigation":187,"path":2718,"proficiencyLevel":2719,"published":2720,"rawbody":2721,"schemaOrg":7,"schemaType":875,"seo":2722,"stem":2723,"__hash__":2724},"blog\u002Fblog\u002Fautocomplete-search-for-swiftui-and-jetpack-compose.md","Autocomplete Search for SwiftUI and Jetpack Compose",{"type":14,"value":2604,"toc":2708},[2605,2608,2622,2625,2629,2639,2642,2648,2652,2655,2664,2666],[17,2606,2602],{"id":2607},"autocomplete-search-for-swiftui-and-jetpack-compose",[24,2609,2610,2611,2616,2617,458],{},"If you've ever tried adding location search to a mobile app,\nyou already know how challenging it can be to get the UI right,\njuggle network data sources, and other headaches.\nToday we're making that easier with composable UI elements\nfor ",[35,2612,2615],{"href":2613,"rel":2614,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fswiftui-autocomplete-search\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch&content=intro",[39],"SwiftUI","\nand ",[35,2618,2621],{"href":2619,"rel":2620,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fjetpack-compose-autocomplete-search\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch&content=intro",[39],"Jetpack Compose",[24,2623,2624],{},"These packages build on top of our existing SDKs for Swift and Kotlin,\nand handle all the API communication for you.\nNo boilerplate.\nWith just a few lines of code, you'll have a UI that \"just works.\"\nAnd once the user selects a result from the list,\nyour code can decide what to do next.\nFor example, you can autofill an address form or start turn-by-turn navigation.",[17,2626,2628],{"id":2627},"keeping-it-customizable","Keeping it customizable",[24,2630,2631,2632,1056,2635,2638],{},"Composable UI frameworks like SwiftUI and Jetpack Compose\nenable many customizations that are difficult or impossible with other approaches—\nall while keeping things easy to use.\nFor example, if you want to customize the look and feel of the list,\njust pass in your own ",[349,2633,2634],{},"View",[349,2636,2637],{},"@Composable",", and we'll use that instead!\nAnd of course, you can use any SwiftUI or Jetpack Compose modifiers\nto change how the view is laid out in your app.",[24,2640,2641],{},"We also provide many customizations for you automatically.\nThe view appearance automatically syncs with your material theme or dark mode preferences,\nso it fits in with the rest of your app.\nAnd we even localize the UI based on device settings,\nso users will see results in their language wherever possible.",[24,2643,2644],{},[1810,2645],{"alt":2646,"src":2647},"Autocomplete Search Example","\u002Fimages\u002Fcontent\u002Fautocomplete-search-localized.png",[28,2649,2651],{"id":2650},"putting-results-in-contextprivately","Putting Results in Context—Privately",[24,2653,2654],{},"Location is critically important context if you want to provide relevant search results.\nFor example, \"London\" might conjure up images of Big Ben for some,\nbut maybe London, Ontario is a bit more relevant if you're in Toronto.\nThat's why our APIs can optionally focus results around a location.",[24,2656,2657,2658,2663],{},"Our new packages support this too and, just like our APIs,\nlocation information is optional.\nAnd if you're in the EU and concerned about GDPR compliance,\nthe new packages support our ",[35,2659,2662],{"href":2660,"rel":2661,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Feu-gdpr-endpoints\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch",[39],"EU endpoints","\nwith a simple flag.",[28,2665,1711],{"id":1710},[56,2667,2668,2679,2692],{},[59,2669,2670,2671,2616,2675,458],{},"Check out our quickstart documentation for ",[35,2672,2615],{"href":2673,"rel":2674,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fswiftui-autocomplete-search\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch&content=next_steps",[39],[35,2676,2621],{"href":2677,"rel":2678,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fjetpack-compose-autocomplete-search\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch&content=next_steps",[39],[59,2680,2681,2682,2686,2687,2691],{},"Find the source code on GitHub (",[35,2683,2615],{"href":2684,"rel":2685,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fswiftui-autocomplete-search",[39]," and ",[35,2688,2621],{"href":2689,"rel":2690,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fjetpack-compose-autocomplete-search",[39],"; give it a star!).",[59,2693,1614,2694,352,2697,2700,2701,2704,2705,1634],{},[35,2695,1248],{"href":1246,"rel":2696,"target":40},[39],[35,2698,1253],{"href":1251,"rel":2699,"target":40},[39],",\nor ",[35,2702,1264],{"href":1262,"rel":2703,"target":40},[39],", or sign-up for\nour ",[35,2706,1633],{"href":1268,"rel":2707,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":2709},[2710,2711],{"id":2650,"depth":172,"text":2651},{"id":1710,"depth":172,"text":1711},"We're making it easier than ever to add autocomplete search to your apps with customizable views for SwiftUI and Jetpack Compose.",[2615,2621,2714,2715,2716],"Autocomplete","Mobile Development","Search UI",{},"\u002Fblog\u002Fautocomplete-search-for-swiftui-and-jetpack-compose","Beginner","2024-10-14","---\ndescription: \"We're making it easier than ever to add autocomplete search to your apps with customizable views for SwiftUI and Jetpack Compose.\"\npublished: 2024-10-14\nkeywords:\n  - SwiftUI\n  - Jetpack Compose\n  - Autocomplete\n  - Mobile Development\n  - Search UI\nschemaType: TechArticle\nproficiencyLevel: Beginner\n---\n\n# Autocomplete Search for SwiftUI and Jetpack Compose\n\nIf you've ever tried adding location search to a mobile app,\nyou already know how challenging it can be to get the UI right,\njuggle network data sources, and other headaches.\nToday we're making that easier with composable UI elements\nfor [SwiftUI](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fswiftui-autocomplete-search\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch&content=intro)\nand [Jetpack Compose](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fjetpack-compose-autocomplete-search\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch&content=intro).\n\nThese packages build on top of our existing SDKs for Swift and Kotlin,\nand handle all the API communication for you.\nNo boilerplate.\nWith just a few lines of code, you'll have a UI that \"just works.\"\nAnd once the user selects a result from the list,\nyour code can decide what to do next.\nFor example, you can autofill an address form or start turn-by-turn navigation.\n\n# Keeping it customizable\n\nComposable UI frameworks like SwiftUI and Jetpack Compose\nenable many customizations that are difficult or impossible with other approaches—\nall while keeping things easy to use.\nFor example, if you want to customize the look and feel of the list,\njust pass in your own `View` or `@Composable`, and we'll use that instead!\nAnd of course, you can use any SwiftUI or Jetpack Compose modifiers\nto change how the view is laid out in your app.\n\nWe also provide many customizations for you automatically.\nThe view appearance automatically syncs with your material theme or dark mode preferences,\nso it fits in with the rest of your app.\nAnd we even localize the UI based on device settings,\nso users will see results in their language wherever possible.\n\n![Autocomplete Search Example](\u002Fimages\u002Fcontent\u002Fautocomplete-search-localized.png)\n\n## Putting Results in Context—Privately\n\nLocation is critically important context if you want to provide relevant search results.\nFor example, \"London\" might conjure up images of Big Ben for some,\nbut maybe London, Ontario is a bit more relevant if you're in Toronto.\nThat's why our APIs can optionally focus results around a location.\n\nOur new packages support this too and, just like our APIs,\nlocation information is optional.\nAnd if you're in the EU and concerned about GDPR compliance,\nthe new packages support our [EU endpoints](https:\u002F\u002Fdocs.stadiamaps.com\u002Feu-gdpr-endpoints\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch){ target=\"_blank\" }\nwith a simple flag.\n\n## Learn More & Next Steps\n\n- Check out our quickstart documentation for [SwiftUI](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fswiftui-autocomplete-search\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch&content=next_steps)\n  and [Jetpack Compose](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fjetpack-compose-autocomplete-search\u002F?utm_source=marketing_site&utm_campaign=composable_autocomplete_launch&content=next_steps).\n- Find the source code on GitHub ([SwiftUI](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fswiftui-autocomplete-search){ target=\"_blank\" } and [Jetpack Compose](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fjetpack-compose-autocomplete-search){ target=\"_blank\" }; give it a star!).\n- Follow Stadia Maps on [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps),\n  or [LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for\n  our [newsletter](https:\u002F\u002Feepurl.com\u002Fgs51fD) to hear about exciting developments first.\n",{"title":2602,"description":2712},"blog\u002Fautocomplete-search-for-swiftui-and-jetpack-compose","2FSZAvysAK7rKMtVXFvFuA6a3J42dRXshuHYidWWaSk",{"id":2726,"title":2727,"abstract":7,"author":7,"body":2728,"description":2850,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":2851,"meta":2854,"modified":7,"navigation":187,"path":2855,"proficiencyLevel":2719,"published":2856,"rawbody":2857,"schemaOrg":7,"schemaType":875,"seo":2858,"stem":2859,"__hash__":2860},"blog\u002Fblog\u002Fmaplibre-swiftui-dsl.md","Our SwiftUI DSL Is Joining the MapLibre Family",{"type":14,"value":2729,"toc":2846},[2730,2733,2748,2780,2783,2787,2790,2799,2801],[17,2731,2727],{"id":2732},"our-swiftui-dsl-is-joining-the-maplibre-family",[24,2734,2735,2736,2741,2742,2747],{},"We're thrilled to announce ",[35,2737,2740],{"href":2738,"rel":2739,"target":40},"https:\u002F\u002Fgithub.com\u002Fmaplibre\u002Fswiftui-dsl",[39],"MapLibre SwiftUI DSL","\nhas graduated from the Stadia Maps labs to become a ",[35,2743,2746],{"href":2744,"rel":2745,"target":40},"https:\u002F\u002Fmaplibre.org\u002F",[39],"MapLibre","-hosted project.\nThe project makes MapLibre a first-class citizen in SwiftUI apps,\nand fills an important gap in the iOS developer experience for MapLibre.",[24,2749,2750,2751,2756,2757,2762,2763,2686,2768,2773,2774,2779],{},"The project began when our co-founder Ian Wagner wanted MapLibre to have a developer experience that rivaled MapKit for SwiftUI.\n",[35,2752,2755],{"href":2753,"rel":2754,"target":40},"https:\u002F\u002Fgithub.com\u002Farchdoog",[39],"Jacob Fielding"," (",[35,2758,2761],{"href":2759,"rel":2760,"target":40},"https:\u002F\u002Frallista.app\u002F",[39],"Rallista","),\n",[35,2764,2767],{"href":2765,"rel":2766,"target":40},"https:\u002F\u002Fsubzero.eu\u002F",[39],"Patrick Wolowicz",[35,2769,2772],{"href":2770,"rel":2771,"target":40},"https:\u002F\u002Fgithub.com\u002FPatrick-Kladek",[39],"Patrick Kladek","\n(",[35,2775,2778],{"href":2776,"rel":2777,"target":40},"https:\u002F\u002Fhudhud.sa\u002Fen",[39],"HudHud",") shared the vision\nand joined the project, contributing significantly to the development and success of the project.\nWe're grateful for their ongoing contributions,\nand for the support from their respective companies.",[24,2781,2782],{},"By transitioning to a MapLibre hosted project,\nthe SwiftUI DSL will have more visibility,\nand will unify ongoing initiatives to make MapLibre work better with SwiftUI.",[28,2784,2786],{"id":2785},"modernizing-the-map-developer-experience","Modernizing the Map Developer Experience",[24,2788,2789],{},"Before the SwiftUI DSL, developers had to build their own wrapper views\nto use MapLibre in a SwiftUI app.\nThis was a lot of work—often duplicating what others had already done—and required a deep understanding of MapLibre Native's Objective-C API.\nThe SwiftUI DSL makes this largely a thing of the past.\nWith just a few lines of code, developers can overlay custom layers, bind the camera to reactive state, and set up custom gestures.",[24,2791,2792,2793,2798],{},"For library authors, the DSL unlocks a whole new level of composability.\nIt's now easy to offer a \"default\" experience that users can customize.\nOur own ",[35,2794,2797],{"href":2795,"rel":2796,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fferrostar\u002F?utm_source=marketing_site&utm_campaign=swiftui_dsl_maplibre",[39],"Ferrostar navigation SDK","\nleverages this pattern,\ngiving developers the power to add custom map layers, overlays, and controls\non top of a map during turn-by-turn navigation.\nThis sort of behavior is extremely difficult and error-prone in UIKit,\nbut is a breeze in SwiftUI.\nWe're excited to see more library authors adopting this approach too.",[28,2800,1711],{"id":1710},[56,2802,2803,2812,2820,2832],{},[59,2804,2805,2806,2811],{},"Check out our ",[35,2807,2810],{"href":2808,"rel":2809,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fnative-multiplatform\u002Fmaplibre-gl-native\u002F?utm_source=marketing_site&utm_campaign=swiftui_dsl_maplibre#ios",[39],"quickstart","\nto build your first map with SwiftUI.",[59,2813,2814,2815,2819],{},"Find the source code on ",[35,2816,2818],{"href":2738,"rel":2817,"target":40},[39],"GitHub"," (and give it a star!).",[59,2821,2822,2823,2826,2827,2831],{},"Join the ",[349,2824,2825],{},"#maplibre-swiftui-compose-playground"," channel in the ",[35,2828,2830],{"href":1237,"rel":2829,"target":40},[39],"OpenStreetMap US Slack"," to get help or join the development effort.",[59,2833,1614,2834,352,2837,2700,2840,2704,2843,1634],{},[35,2835,1248],{"href":1246,"rel":2836,"target":40},[39],[35,2838,1253],{"href":1251,"rel":2839,"target":40},[39],[35,2841,1264],{"href":1262,"rel":2842,"target":40},[39],[35,2844,1633],{"href":1268,"rel":2845,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":2847},[2848,2849],{"id":2785,"depth":172,"text":2786},{"id":1710,"depth":172,"text":1711},"Our SwiftUI DSL makes it easier than ever to build apps with maps. And now it's an official MapLibre project!",[2615,2746,2589,2852,2853],"Maps SDK","DSL",{},"\u002Fblog\u002Fmaplibre-swiftui-dsl","2024-10-07","---\ndescription: \"Our SwiftUI DSL makes it easier than ever to build apps with maps. And now it's an official MapLibre project!\"\npublished: 2024-10-07\nkeywords:\n  - SwiftUI\n  - MapLibre\n  - iOS Development\n  - Maps SDK\n  - DSL\nschemaType: TechArticle\nproficiencyLevel: Beginner\n---\n\n# Our SwiftUI DSL Is Joining the MapLibre Family\n\nWe're thrilled to announce [MapLibre SwiftUI DSL](https:\u002F\u002Fgithub.com\u002Fmaplibre\u002Fswiftui-dsl)\nhas graduated from the Stadia Maps labs to become a [MapLibre](https:\u002F\u002Fmaplibre.org\u002F)-hosted project.\nThe project makes MapLibre a first-class citizen in SwiftUI apps,\nand fills an important gap in the iOS developer experience for MapLibre.\n\nThe project began when our co-founder Ian Wagner wanted MapLibre to have a developer experience that rivaled MapKit for SwiftUI.\n[Jacob Fielding](https:\u002F\u002Fgithub.com\u002Farchdoog){ target=\"_blank\" } ([Rallista](https:\u002F\u002Frallista.app\u002F){ target=\"_blank\" }),\n[Patrick Wolowicz](https:\u002F\u002Fsubzero.eu\u002F){ target=\"_blank\" } and [Patrick Kladek](https:\u002F\u002Fgithub.com\u002FPatrick-Kladek){ target=\"_blank\" }\n([HudHud](https:\u002F\u002Fhudhud.sa\u002Fen){ target=\"_blank\" }) shared the vision\nand joined the project, contributing significantly to the development and success of the project.\nWe're grateful for their ongoing contributions,\nand for the support from their respective companies.\n\nBy transitioning to a MapLibre hosted project,\nthe SwiftUI DSL will have more visibility,\nand will unify ongoing initiatives to make MapLibre work better with SwiftUI.\n\n## Modernizing the Map Developer Experience\n\nBefore the SwiftUI DSL, developers had to build their own wrapper views\nto use MapLibre in a SwiftUI app.\nThis was a lot of work—often duplicating what others had already done—and required a deep understanding of MapLibre Native's Objective-C API.\nThe SwiftUI DSL makes this largely a thing of the past.\nWith just a few lines of code, developers can overlay custom layers, bind the camera to reactive state, and set up custom gestures.\n\nFor library authors, the DSL unlocks a whole new level of composability.\nIt's now easy to offer a \"default\" experience that users can customize.\nOur own [Ferrostar navigation SDK](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fferrostar\u002F?utm_source=marketing_site&utm_campaign=swiftui_dsl_maplibre)\nleverages this pattern,\ngiving developers the power to add custom map layers, overlays, and controls\non top of a map during turn-by-turn navigation.\nThis sort of behavior is extremely difficult and error-prone in UIKit,\nbut is a breeze in SwiftUI.\nWe're excited to see more library authors adopting this approach too.\n\n## Learn More & Next Steps\n\n- Check out our [quickstart](https:\u002F\u002Fdocs.stadiamaps.com\u002Fnative-multiplatform\u002Fmaplibre-gl-native\u002F?utm_source=marketing_site&utm_campaign=swiftui_dsl_maplibre#ios){ target=\"_blank\" }\n  to build your first map with SwiftUI.\n- Find the source code on [GitHub](https:\u002F\u002Fgithub.com\u002Fmaplibre\u002Fswiftui-dsl){ target=\"_blank\" } (and give it a star!).\n- Join the `#maplibre-swiftui-compose-playground` channel in the [OpenStreetMap US Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) to get help or join the development effort.\n- Follow Stadia Maps on [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps),\n  or [LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for\n  our [newsletter](https:\u002F\u002Feepurl.com\u002Fgs51fD) to hear about exciting developments first.\n",{"title":2727,"description":2850},"blog\u002Fmaplibre-swiftui-dsl","Ncwtkkjwjlne0gRj-6jbkPg78PNI_rB23R9yxDFd7N4",{"id":2862,"title":2863,"abstract":7,"author":7,"body":2864,"description":3180,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":3181,"meta":3185,"modified":7,"navigation":187,"path":3186,"proficiencyLevel":7,"published":3187,"rawbody":3188,"schemaOrg":7,"schemaType":7,"seo":3189,"stem":3190,"__hash__":3191},"blog\u002Fblog\u002F2024-matrix-navigation-credit-updates.md","Fall 2024 Credit Schedule Updates",{"type":14,"value":2865,"toc":3169},[2866,2869,2872,2875,2879,2882,2886,2889,2893,2911,2914,2918,2926,2941,2945,2948,2952,2955,2959,2962,3136,3138],[17,2867,2863],{"id":2868},"fall-2024-credit-schedule-updates",[24,2870,2871],{},"For nearly a decade, we’ve helped companies build successful products using location APIs by delivering private,\nfinancially scalable services backed by exceptional human support. In the last two years, we’ve launched two major\nproduct lines: Geocoding and Satellite Imagery, and, in the background, we’ve significantly expanded our Routing API\ncapabilities. With all of these improvements and new functionality, we’re updating our API credit schedule. Current\npricing plans, including base price and additional credit rates, will remain unchanged.",[24,2873,2874],{},"Starting October 1st, we're reducing credits used by all Geocoding, Autocomplete Search, and Isochrone APIs.\nFor some Routing and Matrix APIs, we're increasing credits used.\nWe’re also opening the Optimized Routing and Matrix APIs to the Standard Plan,\nallowing more customers take advantage of our most advanced APIs.",[28,2876,2878],{"id":2877},"even-more-affordable-geocoding","Even More Affordable Geocoding",[24,2880,2881],{},"Our Geocoding product graduated out of beta just over a year ago, and since then, we’ve reached new levels of scale.\nThis allows us to reduce credit used from 30 to 20 credits per API request—a 30% reduction. The update\napplies to all geocoding and autocomplete search endpoints.",[28,2883,2885],{"id":2884},"improved-routing-timedistance-matrix","Improved Routing & Time\u002FDistance Matrix",[24,2887,2888],{},"Routing is one of our oldest services, and over the years, we’ve built it into a world-class product,\nwith customizability few providers can match.\nToday it gets a little bit better.",[1205,2890,2892],{"id":2891},"voice-banner-navigation-aids-for-routing-map-matching","Voice & Banner Navigation Aids for Routing & Map Matching",[24,2894,2895,2896,2616,2900,2905,2906,2910],{},"Available immediately,\nour ",[35,2897,179],{"href":2898,"rel":2899,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],[35,2901,2904],{"href":2902,"rel":2903,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fmap-matching\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],"Map Matching","\nAPIs will support navigation aids,\nincluding detailed maneuver information optimized for display,\nand voice prompts in over 25 languages.\nThe new navigation aids are available in OSRM format,\nwhich is used by many mobile SDKs,\nincluding our own ",[35,2907,1795],{"href":2908,"rel":2909,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fferrostar\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],". Where available, these responses also include detailed\nintersection information and speed limits in a single API request.",[24,2912,2913],{},"Each request including these aids will use 30 credits and are available to all Stadia Maps accounts.",[1205,2915,2917],{"id":2916},"bigger-better-matrices","Bigger, Better Matrices",[24,2919,578,2920,2925],{},[35,2921,2924],{"href":2922,"rel":2923,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Ftime-distance-matrix\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],"Time\u002FDistance Matrix API","\nis a critical component for many logistics applications,\nincluding solving the Rich Vehicle Routing Problem.\nUntil now, we’ve had to severely limit our matrix offering.\nThanks to recent infrastructure enhancements, we’re excited to introduce the following major improvements:",[107,2927,2928,2931,2934],{},[59,2929,2930],{},"We're opening the Matrix API to Standard Plan users. Previously, this was limited to our Professional and Enterprise\nPlans.",[59,2932,2933],{},"We’re increasing the maximum matrix element count by a factor of 10: from 1,000 to 10,000 (for the Professional\nPlan).",[59,2935,2936,2937],{},"We're offering matrices larger than 10,000 elements by custom agreement. ",[35,2938,2940],{"href":2939},"mailto:entsales@stadiamaps.com?subject=Time%2FDistance%20Matrix%20Limits","Contact us to learn more.",[1205,2942,2944],{"id":2943},"matrix-billing-updates","Matrix Billing Updates",[24,2946,2947],{},"Matrix API requests will now calculate used credits differently.\nInstead of a flat number credits per request, the Matrix API will use credits per matrix element.\nEach matrix element will consume 10 credits, with no additional charge per request.\nThis adjustment reflects the varying sizes of matrix requests and aligns with industry standard practice.\nIt also enables us to support larger matrices more effectively going forward.",[1205,2949,2951],{"id":2950},"other-routing-credit-changes","Other Routing Credit Changes",[24,2953,2954],{},"Isochrone (reachable range) requests will use fewer credits, at 20 credits per request.\nOptimized and Standard routing requests will use more credits, at 40 and 20 credits per request, respectively.",[28,2956,2958],{"id":2957},"credit-change-overview","Credit Change Overview",[24,2960,2961],{},"Since we’ve made quite a few adjustments to the credit schedule, here’s an overview of the changes:",[2195,2963,2964,2977],{},[2198,2965,2966],{},[2201,2967,2968,2971,2974],{},[2204,2969,2970],{},"API",[2204,2972,2973],{},"Previous",[2204,2975,2976],{},"Updated",[2211,2978,2979,2998,3013,3026,3038,3061,3074,3086,3098,3111,3123],{},[2201,2980,2981,2988,2991],{},[2216,2982,2983],{},[35,2984,2987],{"href":2985,"rel":2986,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Foptimized-routing\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],"Optimized routing",[2216,2989,2990],{},"30 credits per request",[2216,2992,2993,2994,2997],{},"40 credits per request & ",[2995,2996],"br",{}," available on the Standard Plan",[2201,2999,3000,3007,3010],{},[2216,3001,3002],{},[35,3003,3006],{"href":3004,"rel":3005,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fstandard-routing\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],"Standard routing",[2216,3008,3009],{},"10 credits per request",[2216,3011,3012],{},"20 credits per request",[2201,3014,3015,3021,3024],{},[2216,3016,3017],{},[35,3018,3020],{"href":3004,"rel":3019,"target":40},[39],"Standard routing (OSRM Format)",[2216,3022,3023],{},"-",[2216,3025,2990],{},[2201,3027,3028,3034,3036],{},[2216,3029,3030],{},[35,3031,3033],{"href":2902,"rel":3032,"target":40},[39],"Map matching (OSRM Format)",[2216,3035,3023],{},[2216,3037,2990],{},[2201,3039,3040,3046,3052],{},[2216,3041,3042],{},[35,3043,3045],{"href":2922,"rel":3044,"target":40},[39],"Matrix",[2216,3047,3048,3049],{},"30 credits ",[611,3050,3051],{},"per request",[2216,3053,3054,3055,3058,3059,2997],{},"10 credits ",[611,3056,3057],{},"per element"," & ",[2995,3060],{},[2201,3062,3063,3070,3072],{},[2216,3064,3065],{},[35,3066,3069],{"href":3067,"rel":3068,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fisochrones\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],"Isochrones",[2216,3071,2990],{},[2216,3073,3012],{},[2201,3075,3076,3082,3084],{},[2216,3077,3078],{},[35,3079,1288],{"href":3080,"rel":3081,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fsearch\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],[2216,3083,2990],{},[2216,3085,3012],{},[2201,3087,3088,3094,3096],{},[2216,3089,3090],{},[35,3091,1287],{"href":3092,"rel":3093,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Freverse-search\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],[2216,3095,2990],{},[2216,3097,3012],{},[2201,3099,3100,3107,3109],{},[2216,3101,3102],{},[35,3103,3106],{"href":3104,"rel":3105,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fstructured-search\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],"Structured Geocoding",[2216,3108,2990],{},[2216,3110,3012],{},[2201,3112,3113,3119,3121],{},[2216,3114,3115],{},[35,3116,1507],{"href":3117,"rel":3118,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fautocomplete\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],[2216,3120,2990],{},[2216,3122,3012],{},[2201,3124,3125,3132,3134],{},[2216,3126,3127],{},[35,3128,3131],{"href":3129,"rel":3130,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fplace-lookup\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],"Place Lookup",[2216,3133,2990],{},[2216,3135,3012],{},[28,3137,1711],{"id":1710},[56,3139,3140,3147,3155],{},[59,3141,3142,3146],{},[35,3143,1720],{"href":3144,"rel":3145,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news",[39],"\nto get your API key. You can start building today without a credit card!",[59,3148,1231,3149,1056,3152,1240],{},[35,3150,849],{"href":847,"rel":3151,"target":40},[39],[35,3153,1239],{"href":1237,"rel":3154,"target":40},[39],[59,3156,1243,3157,352,3160,2700,3163,2704,3166,1271],{},[35,3158,1248],{"href":1246,"rel":3159,"target":40},[39],[35,3161,1253],{"href":1251,"rel":3162,"target":40},[39],[35,3164,1264],{"href":1262,"rel":3165,"target":40},[39],[35,3167,1270],{"href":1268,"rel":3168,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":3170},[3171,3172,3178,3179],{"id":2877,"depth":172,"text":2878},{"id":2884,"depth":172,"text":2885,"children":3173},[3174,3175,3176,3177],{"id":2891,"depth":669,"text":2892},{"id":2916,"depth":669,"text":2917},{"id":2943,"depth":669,"text":2944},{"id":2950,"depth":669,"text":2951},{"id":2957,"depth":172,"text":2958},{"id":1710,"depth":172,"text":1711},"Increased matrix element limits, navigation aids with OSRM support for routing, and adjustments to the credit schedule.",[183,180,3182,3183,3184],"OSRM","Credits","Pricing",{},"\u002Fblog\u002F2024-matrix-navigation-credit-updates","2024-09-12","---\ndescription: \"Increased matrix element limits, navigation aids with OSRM support for routing, and adjustments to the credit schedule.\"\npublished: 2024-09-12\nkeywords:\n  - Matrix Routing\n  - Navigation\n  - OSRM\n  - Credits\n  - Pricing\n---\n\n# Fall 2024 Credit Schedule Updates\n\nFor nearly a decade, we’ve helped companies build successful products using location APIs by delivering private,\nfinancially scalable services backed by exceptional human support. In the last two years, we’ve launched two major\nproduct lines: Geocoding and Satellite Imagery, and, in the background, we’ve significantly expanded our Routing API\ncapabilities. With all of these improvements and new functionality, we’re updating our API credit schedule. Current \npricing plans, including base price and additional credit rates, will remain unchanged.\n\nStarting October 1st, we're reducing credits used by all Geocoding, Autocomplete Search, and Isochrone APIs.\nFor some Routing and Matrix APIs, we're increasing credits used. \nWe’re also opening the Optimized Routing and Matrix APIs to the Standard Plan, \nallowing more customers take advantage of our most advanced APIs.\n\n## Even More Affordable Geocoding\n\nOur Geocoding product graduated out of beta just over a year ago, and since then, we’ve reached new levels of scale.\nThis allows us to reduce credit used from 30 to 20 credits per API request—a 30% reduction. The update\napplies to all geocoding and autocomplete search endpoints.\n\n## Improved Routing & Time\u002FDistance Matrix\n\nRouting is one of our oldest services, and over the years, we’ve built it into a world-class product, \nwith customizability few providers can match. \nToday it gets a little bit better.\n\n### Voice & Banner Navigation Aids for Routing & Map Matching\n\nAvailable immediately, \nour [Routing](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news){ target=\"_blank\" }\nand [Map Matching](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fmap-matching\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news){ target=\"_blank\" }\nAPIs will support navigation aids, \nincluding detailed maneuver information optimized for display, \nand voice prompts in over 25 languages. \nThe new navigation aids are available in OSRM format,\nwhich is used by many mobile SDKs, \nincluding our own [Ferrostar](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fferrostar\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news){ target=\"_blank\" }. Where available, these responses also include detailed\nintersection information and speed limits in a single API request.\n\nEach request including these aids will use 30 credits and are available to all Stadia Maps accounts.\n\n### Bigger, Better Matrices\n\nOur [Time\u002FDistance Matrix API](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Ftime-distance-matrix\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news){target=_blank} \nis a critical component for many logistics applications, \nincluding solving the Rich Vehicle Routing Problem. \nUntil now, we’ve had to severely limit our matrix offering. \nThanks to recent infrastructure enhancements, we’re excited to introduce the following major improvements:\n\n1. We're opening the Matrix API to Standard Plan users. Previously, this was limited to our Professional and Enterprise\n   Plans.\n2. We’re increasing the maximum matrix element count by a factor of 10: from 1,000 to 10,000 (for the Professional\n   Plan).\n3. We're offering matrices larger than 10,000 elements by custom agreement. [Contact us to learn more.](mailto:entsales@stadiamaps.com?subject=Time%2FDistance%20Matrix%20Limits)\n\n### Matrix Billing Updates\n\nMatrix API requests will now calculate used credits differently. \nInstead of a flat number credits per request, the Matrix API will use credits per matrix element. \nEach matrix element will consume 10 credits, with no additional charge per request. \nThis adjustment reflects the varying sizes of matrix requests and aligns with industry standard practice. \nIt also enables us to support larger matrices more effectively going forward.\n\n### Other Routing Credit Changes\n\nIsochrone (reachable range) requests will use fewer credits, at 20 credits per request. \nOptimized and Standard routing requests will use more credits, at 40 and 20 credits per request, respectively.\n\n## Credit Change Overview\n\nSince we’ve made quite a few adjustments to the credit schedule, here’s an overview of the changes:\n\n| API                                                                                                                                                                                                                           | Previous                 | Updated                                                        |\n|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------|----------------------------------------------------------------|\n| [Optimized routing](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Foptimized-routing\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)                          | 30 credits per request   | 40 credits per request & \u003Cbr> available on the Standard Plan   |\n| [Standard routing](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fstandard-routing\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)                            | 10 credits per request   | 20 credits per request                                         |\n| [Standard routing (OSRM Format)](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fstandard-routing\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)              | -                        | 30 credits per request                                         |\n| [Map matching (OSRM Format)](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fmap-matching\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)                      | -                        | 30 credits per request                                         |\n| [Matrix](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Ftime-distance-matrix\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)                                  | 30 credits *per request* | 10 credits *per element* & \u003Cbr> available on the Standard Plan |\n| [Isochrones](https:\u002F\u002Fdocs.stadiamaps.com\u002Frouting\u002Fisochrones\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)                                        | 30 credits per request   | 20 credits per request                                         |\n| [Forward Geocoding](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fsearch\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)               | 30 credits per request   | 20 credits per request                                         |\n| [Reverse Geocoding](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Freverse-search\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)       | 30 credits per request   | 20 credits per request                                         |\n| [Structured Geocoding](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fstructured-search\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news) | 30 credits per request   | 20 credits per request                                         |\n| [Autocomplete Search](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fautocomplete\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)       | 30 credits per request   | 20 credits per request                                         |\n| [Place Lookup](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fplace-lookup\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)              | 30 credits per request   | 20 credits per request                                         |\n\n## Learn More & Next Steps\n\n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_campaign=matrix_navigation_credit_updates&utm_content=matrix_navigation_credit_update_news)\n  to get your API key. You can start building today without a credit card!\n- Join our community on [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT) or [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) to share what you're working on or get help.\n- Follow us on [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps),\n  or [LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for\n  our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD) to stay up to date.",{"title":2863,"description":3180},"blog\u002F2024-matrix-navigation-credit-updates","A2CSKk6bNjHWcBk6ZOJ-AjFwzifVRe1eUwXCpuCREWk",{"id":3193,"title":3194,"abstract":7,"author":7,"body":3195,"description":3311,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":3312,"meta":3318,"modified":7,"navigation":187,"path":3319,"proficiencyLevel":7,"published":3320,"rawbody":3321,"schemaOrg":7,"schemaType":7,"seo":3322,"stem":3323,"__hash__":3324},"blog\u002Fblog\u002Fquickly-geocode-thousands-of-addresses-with-bulk-geocoding.md","Bulk Geocoding API Is Now Available",{"type":14,"value":3196,"toc":3305},[3197,3200,3209,3213,3227,3230,3233,3237,3244,3248,3266,3268],[17,3198,3194],{"id":3199},"bulk-geocoding-api-is-now-available",[24,3201,3202,3203,3208],{},"Since we launched our geocoding product,\nwe've learned a lot about what developers need to build applications that convert addresses, places, and more to coordinates.\nWhile we've always supported forward, reverse, and structured queries,\none thing we haven't supported is making multiple queries in one request.\nBulk (also known as batch) geocoding makes it faster and simpler to geocode many addresses at once.\nWhether supporting a batch job or improving performance of multiple simultaneous requests,\nour new ",[35,3204,3207],{"href":3205,"rel":3206,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fbulk-geocoding-search\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement&utm_content=bulk_intro",[39],"Bulk Geocoding API"," helps developers build more efficient solutions based on the same, high-quality Geocoding API they already know.",[28,3210,3212],{"id":3211},"make-up-to-5000-queriessimultaneously","Make up to 5000 Queries—Simultaneously",[24,3214,3215,3216,2616,3221,3226],{},"With the new API, you can make up to 5,000 geocoding queries with a single HTTP request.\nBoth ",[35,3217,3220],{"href":3218,"rel":3219,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fsearch\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement",[39],"forward geocoding",[35,3222,3225],{"href":3223,"rel":3224,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fstructured-search\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement",[39],"structured geocoding","\nare supported. You can even combine multiple requests types in a single bulk request!",[24,3228,3229],{},"By using the bulk endpoint instead of individual requests, your queries will be faster.\nThe endpoints' internal parallelization will simultaneously improve throughput, reduce total latency, and simplify the calling code.\nThis new endpoint is useful in environments without easy access to lightweight concurrency and connection pooling,\nwhere each request incurs the connection establishment overhead.\nOlder web frameworks, lower-level code, and shell scripts will especially benefit from opting for the bulk endpoint over the standard endpoints.",[24,3231,3232],{},"For particularly latency sensitive applications, you can also process the results as they are produced.\nThe endpoint streams the results back as a JSON body, enabling much lower time-to-first-result if required.",[28,3234,3236],{"id":3235},"the-same-simple-affordable-pricing","The Same Simple, Affordable Pricing",[24,3238,3239,3240,458],{},"Bulk geocoding is available for all accounts subscribed to our Standard and Professional plans.\nEach request consumes credits as if you made a request to underlying endpoint directly,\nso there's no additional fees or credits used.\nYou can find how many credits each API call consumes in our ",[35,3241,3243],{"href":3242},"\u002Fpricing\u002F#credit-schedule","credit schedule",[28,3245,3247],{"id":3246},"available-in-our-sdks-curl-and-everything-in-between","Available in our SDKs, cURL, and Everything In-Between",[24,3249,3250,3251,3255,3256,3259,3260,3265],{},"As usual, our official ",[35,3252,1159],{"href":3253,"rel":3254,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement#apis",[39]," are already updated with support for the new API.\nYou can access it from JavaScript, Python, Kotlin, Swift or PHP without writing any new network or parsing code!\nYou can even find a ",[349,3257,3258],{},"curl"," example in our ",[35,3261,3264],{"href":3262,"rel":3263,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fbulk-geocoding-search\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement&utm_content=available_everywhere",[39],"API documentation"," so your shell scripts aren't left behind.",[28,3267,1711],{"id":1710},[56,3269,3270,3276,3283,3291],{},[59,3271,3272,1721],{},[35,3273,1720],{"href":3274,"rel":3275,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_medium=blog&utm_campaign=bulk_geocoding_accounement",[39],[59,3277,504,3278,458],{},[35,3279,3282],{"href":3280,"rel":3281,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fbulk-geocoding-search\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement&utm_content=bulk_next_steps",[39],"bulk geocoding API documentation and sample code",[59,3284,1231,3285,1056,3288,1240],{},[35,3286,849],{"href":847,"rel":3287,"target":40},[39],[35,3289,1239],{"href":1237,"rel":3290,"target":40},[39],[59,3292,1243,3293,352,3296,1749,3299,1753,3302,1271],{},[35,3294,1248],{"href":1246,"rel":3295,"target":40},[39],[35,3297,1253],{"href":1251,"rel":3298,"target":40},[39],[35,3300,1264],{"href":1262,"rel":3301,"target":40},[39],[35,3303,1270],{"href":1268,"rel":3304,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":3306},[3307,3308,3309,3310],{"id":3211,"depth":172,"text":3212},{"id":3235,"depth":172,"text":3236},{"id":3246,"depth":172,"text":3247},{"id":1710,"depth":172,"text":1711},"Announcing Bulk Geocoding: we're making it easier to geocode large datasets with our bulk geocoding API.",[3313,3314,3315,3316,3317],"Bulk Geocoding","Batch Processing","Address Lookup","Geocoding API","Data Processing",{},"\u002Fblog\u002Fquickly-geocode-thousands-of-addresses-with-bulk-geocoding","2024-08-23","---\ndescription: \"Announcing Bulk Geocoding: we're making it easier to geocode large datasets with our bulk geocoding API.\"\npublished: \"2024-08-23\"\nkeywords:\n  - Bulk Geocoding\n  - Batch Processing\n  - Address Lookup\n  - Geocoding API\n  - Data Processing\n---\n\n# Bulk Geocoding API Is Now Available\n\nSince we launched our geocoding product, \nwe've learned a lot about what developers need to build applications that convert addresses, places, and more to coordinates. \nWhile we've always supported forward, reverse, and structured queries, \none thing we haven't supported is making multiple queries in one request.\nBulk (also known as batch) geocoding makes it faster and simpler to geocode many addresses at once.\nWhether supporting a batch job or improving performance of multiple simultaneous requests,\nour new [Bulk Geocoding API](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fbulk-geocoding-search\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement&utm_content=bulk_intro){ target=\"_blank\" } helps developers build more efficient solutions based on the same, high-quality Geocoding API they already know.\n\n## Make up to 5000 Queries—Simultaneously\n\nWith the new API, you can make up to 5,000 geocoding queries with a single HTTP request. \nBoth [forward geocoding](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fsearch\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement){ target=\"_blank\" }\nand [structured geocoding](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fstructured-search\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement){ target=\"_blank\" }\nare supported. You can even combine multiple requests types in a single bulk request!\n\nBy using the bulk endpoint instead of individual requests, your queries will be faster. \nThe endpoints' internal parallelization will simultaneously improve throughput, reduce total latency, and simplify the calling code.\nThis new endpoint is useful in environments without easy access to lightweight concurrency and connection pooling, \nwhere each request incurs the connection establishment overhead. \nOlder web frameworks, lower-level code, and shell scripts will especially benefit from opting for the bulk endpoint over the standard endpoints.\n\nFor particularly latency sensitive applications, you can also process the results as they are produced. \nThe endpoint streams the results back as a JSON body, enabling much lower time-to-first-result if required.\n\n## The Same Simple, Affordable Pricing\n\nBulk geocoding is available for all accounts subscribed to our Standard and Professional plans.\nEach request consumes credits as if you made a request to underlying endpoint directly,\nso there's no additional fees or credits used.\nYou can find how many credits each API call consumes in our [credit schedule](\u002Fpricing\u002F#credit-schedule).\n\n## Available in our SDKs, cURL, and Everything In-Between\n\nAs usual, our official [SDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement#apis){ target=\"_blank\" } are already updated with support for the new API.\nYou can access it from JavaScript, Python, Kotlin, Swift or PHP without writing any new network or parsing code!\nYou can even find a `curl` example in our [API documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fbulk-geocoding-search\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement&utm_content=available_everywhere) so your shell scripts aren't left behind.\n\n## Learn More & Next Steps\n\n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_medium=blog&utm_campaign=bulk_geocoding_accounement) to get an API key. You can start building today without a credit card!\n- Read the [bulk geocoding API documentation and sample code](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Fbulk-geocoding-search\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=bulk_geocoding_accounement&utm_content=bulk_next_steps).\n- Join our community on [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT) or [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) to share what you're working on or get help.\n- Follow us on [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps), or\n  [LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD) to stay up to date.\n",{"title":3194,"description":3311},"blog\u002Fquickly-geocode-thousands-of-addresses-with-bulk-geocoding","9QlY8hF8wAh1471jY5wPoKPTWrLX5qsPyYlfQsGWlCk",{"id":3326,"title":3327,"abstract":7,"author":7,"body":3328,"description":3469,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":3470,"meta":3473,"modified":7,"navigation":187,"path":3474,"proficiencyLevel":7,"published":3475,"rawbody":3476,"schemaOrg":7,"schemaType":7,"seo":3477,"stem":3478,"__hash__":3479},"blog\u002Fblog\u002Fnew-sdk-php.md","Official SDK for PHP is Now Available",{"type":14,"value":3329,"toc":3462},[3330,3333,3342,3346,3349,3360,3364,3373,3393,3397,3400,3404,3421,3423],[17,3331,3327],{"id":3332},"official-sdk-for-php-is-now-available",[24,3334,3335,3336,3341],{},"Today we are happy to announce the initial release of our ",[35,3337,3340],{"href":3338,"rel":3339,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fphp\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news",[39],"PHP SDK",".\nThis SDK makes it easier than ever to access geocoding, routing, elevation,\nand time zone information in PHP.",[28,3343,3345],{"id":3344},"improving-the-developer-experience","Improving the Developer Experience",[24,3347,3348],{},"Before today, PHP developers accessed the Stadia Maps APIs\nusing an HTTP library (such as cURL) and some JSON processing code.\nWhile our APIs are easy to integrate with using standard HTTP libraries,\nthere are several reasons to use one of our SDKs:",[56,3350,3351,3354,3357],{},[59,3352,3353],{},"Less code to maintain—our SDKs handle the API integration for you!",[59,3355,3356],{},"Discover the API through autocomplete and documentation without leaving your IDE.",[59,3358,3359],{},"Immediately discover and use new features with a package updates. We're always improving our APIs, and we keep the SDKs in sync.",[28,3361,3363],{"id":3362},"our-seventh-sdk","Our Seventh SDK",[24,3365,3366,3367,3372],{},"We're always speaking with users,\nso when the need of a PHP SDK came up a few times,\nwe saw an opportunity to make development easier.\nThanks to our existing ",[35,3368,3371],{"href":3369,"rel":3370,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fapi-reference\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news",[39],"OpenAPI spec","\nand experience packaging for other languages,\nwe published the first release in less than a day!",[24,3374,3375,3376,3381,3382,3387,3388,458],{},"The PHP SDK is our seventh official SDK,\nand complements our existing API clients for TypeScript, Python, Kotlin, and Swift.\nNow, if you're counting carefully, you may have noticed that we only mentioned five.\nThat's because we also have an ",[35,3377,3380],{"href":3378,"rel":3379,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fmaplibre-gl-js-autocomplete-search-plugin\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news",[39],"autocomplete search plugin for MapLibre GL JS",",\nand a ",[35,3383,3386],{"href":3384,"rel":3385,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fferrostar\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news",[39],"mobile turn-by-turn navigation SDK",".\nYou can learn more about all of our SDKs at ",[35,3389,3392],{"href":3390,"rel":3391,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news",[39],"docs.stadiamaps.com",[28,3394,3396],{"id":3395},"we-want-your-feedback","We Want Your Feedback",[24,3398,3399],{},"Are you a PHP developer?\nWe'd love to hear your thoughts on the new SDK!\nLet us know how you're using it, and how we can make it better.\nYour feedback helps us continuously improve the SDKs.",[28,3401,3403],{"id":3402},"where-to-get-it","Where to Get It",[24,3405,3406,3407,3412,3413,3416,3417,458],{},"Do you use Composer?\nWe've hosted the package on ",[35,3408,3411],{"href":3409,"rel":3410,"target":40},"https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fstadiamaps\u002Fapi",[39],"Packagist","\nfor easy installation with ",[349,3414,3415],{},"composer install",".\nAnd if you'd prefer to just download the files directly,\nyou can do that too!\nLike all of our SDKs, it's completely open-source,\nand you can find the code and installation instructions\non ",[35,3418,2818],{"href":3419,"rel":3420,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-php",[39],[28,3422,1711],{"id":1710},[56,3424,3425,3433,3440],{},[59,3426,3427,3428,3432],{},"Read our ",[35,3429,3431],{"href":3390,"rel":3430,"target":40},[39],"SDK documentation"," for installation instructions and example code.",[59,3434,3435,3439],{},[35,3436,1720],{"href":3437,"rel":3438,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=php_sdk_launch&utm_content=php_sdk_announcement",[39]," to get an API key. Start building today without a credit card!",[59,3441,1231,3442,1056,3445,3448,3449,352,3452,1749,3455,1753,3458,3461],{},[35,3443,1239],{"href":1237,"rel":3444,"target":40},[39],[35,3446,849],{"href":847,"rel":3447,"target":40},[39],", follow us\non ",[35,3450,1248],{"href":1246,"rel":3451,"target":40},[39],[35,3453,1253],{"href":1251,"rel":3454,"target":40},[39],[35,3456,1264],{"href":1262,"rel":3457,"target":40},[39],[35,3459,1270],{"href":1268,"rel":3460,"target":40},[39],"!",{"title":168,"searchDepth":169,"depth":169,"links":3463},[3464,3465,3466,3467,3468],{"id":3344,"depth":172,"text":3345},{"id":3362,"depth":172,"text":3363},{"id":3395,"depth":172,"text":3396},{"id":3402,"depth":172,"text":3403},{"id":1710,"depth":172,"text":1711},"We're making it easier to access geocoding, routing, elevation, and time zone APIs in PHP.",[3340,3471,3472,402,179],"Backend Development","API Client",{},"\u002Fblog\u002Fnew-sdk-php","2024-07-26","---\ndescription: \"We're making it easier to access geocoding, routing, elevation, and time zone APIs in PHP.\"\npublished: \"2024-07-26\"\nkeywords:\n  - PHP SDK\n  - Backend Development\n  - API Client\n  - Geocoding\n  - Routing\n---\n\n# Official SDK for PHP is Now Available\n\nToday we are happy to announce the initial release of our [PHP SDK](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fphp\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news){ target=\"_blank\" }.\nThis SDK makes it easier than ever to access geocoding, routing, elevation,\nand time zone information in PHP.\n\n## Improving the Developer Experience\n\nBefore today, PHP developers accessed the Stadia Maps APIs\nusing an HTTP library (such as cURL) and some JSON processing code.\nWhile our APIs are easy to integrate with using standard HTTP libraries,\nthere are several reasons to use one of our SDKs:\n\n* Less code to maintain—our SDKs handle the API integration for you!\n* Discover the API through autocomplete and documentation without leaving your IDE.\n* Immediately discover and use new features with a package updates. We're always improving our APIs, and we keep the SDKs in sync.\n\n## Our Seventh SDK\n\nWe're always speaking with users,\nso when the need of a PHP SDK came up a few times,\nwe saw an opportunity to make development easier.\nThanks to our existing [OpenAPI spec](https:\u002F\u002Fdocs.stadiamaps.com\u002Fapi-reference\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news){ target=\"_blank\" }\nand experience packaging for other languages,\nwe published the first release in less than a day!\n\nThe PHP SDK is our seventh official SDK,\nand complements our existing API clients for TypeScript, Python, Kotlin, and Swift.\nNow, if you're counting carefully, you may have noticed that we only mentioned five.\nThat's because we also have an [autocomplete search plugin for MapLibre GL JS](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fmaplibre-gl-js-autocomplete-search-plugin\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news){ target=\"_blank\" },\nand a [mobile turn-by-turn navigation SDK](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fferrostar\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news){ target=\"_blank\" }.\nYou can learn more about all of our SDKs at [docs.stadiamaps.com](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news){ target=\"_blank\" }.\n\n## We Want Your Feedback\n\nAre you a PHP developer?\nWe'd love to hear your thoughts on the new SDK!\nLet us know how you're using it, and how we can make it better.\nYour feedback helps us continuously improve the SDKs.\n\n## Where to Get It\n\nDo you use Composer?\nWe've hosted the package on [Packagist](https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fstadiamaps\u002Fapi){ target=\"_blank\" }\nfor easy installation with `composer install`. \nAnd if you'd prefer to just download the files directly,\nyou can do that too!\nLike all of our SDKs, it's completely open-source,\nand you can find the code and installation instructions\non [GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-php){ target=\"_blank\" }.\n\n## Learn More & Next Steps\n\n- Read our [SDK documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F?utm_source=marketing_site&utm_campaign=php_sdk_launch&utm_content=php_announcement_news){ target=\"_blank\" } for installation instructions and example code.\n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=php_sdk_launch&utm_content=php_sdk_announcement) to get an API key. Start building today without a credit card!\n- Join our community on [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) or [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT), follow us\n  on [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps), or\n  [LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD)!\n\n",{"title":3327,"description":3469},"blog\u002Fnew-sdk-php","1z-yuIWhKyRwhsnmRRkhxsUydQp4jwJOcInOnQvIXQU",{"id":3481,"title":3482,"abstract":7,"author":7,"body":3483,"description":3848,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":3849,"meta":3853,"modified":7,"navigation":187,"path":3854,"proficiencyLevel":7,"published":3855,"rawbody":3856,"schemaOrg":7,"schemaType":7,"seo":3857,"stem":3858,"__hash__":3859},"blog\u002Fblog\u002Fcustom-markers-in-static-map-images.md","Custom markers and POST support for Static Maps",{"type":14,"value":3484,"toc":3842},[3485,3488,3491,3495,3498,3501,3504,3510,3514,3517,3525,3528,3531,3817,3821,3824,3828,3840],[17,3486,3482],{"id":3487},"custom-markers-and-post-support-for-static-maps",[24,3489,3490],{},"Static Maps are the fastest ways to add maps to your website or app.\nSince each map is a single PNG or JPEG,\nthey are a lot easier to set up than interactive maps.\nYou can even add markers and lines to static maps—our servers handle the hard work.",[28,3492,3494],{"id":3493},"custom-marker-images","Custom marker images",[24,3496,3497],{},"Today you can add markers to a static map by including the coordinates in your request.\nWe’ll automatically select a suitable image based on the map style.\nYou can also use a labeled marker with a classic solid design for differentiation.",[24,3499,3500],{},"Today, we’re letting you go even further with branding and improved differentiation.\nJust send us the image URL in your request to customize the marker image!\nThis feature is now available on all plans that have access to static maps\n(including free trials).",[24,3502,3503],{},"We’re launching with support for up to 5 custom marker images per request,\ngiving you plenty of flexibility.\nAnd the images can be up to 128px in each dimension,\nso your carefully designed icons will look great on retina and other HiDPI screens.",[24,3505,3506],{},[1810,3507],{"alt":3508,"src":3509},"Static Map","https:\u002F\u002Ftiles.stadiamaps.com\u002Fstatic\u002Falidade_smooth.png?center=59.438484,24.742595&zoom=14&l=oj_kpBkhmen@vFvDlStSdIzN%60BxCfMfShA%60B~@%7CAvCrDpG%60FfVfRb%5CzSrBdBhZx%5CpFdM~BpFn@zAxCrHrH%7CQjOh_@NtM%7CVv@d@aHdHEfD%5E%5CDhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG%5DcEc@%7BFm@uF%5DoDgAwJhAm@vMqGoAs%7B@dAMfG_@dE_@Ezb@ExWzBBZ?L@%7CDnTtAqE~CyMp@sB%7C@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA%7D@~CVbB%60@pDtAN%7DDxD%60AdFi@vBIxBIe@aMuAgPyFwy@%7BCa_@yFar@%5B%7BC_AsGuAkGqEgY_CmLqAuFuHi%5Bm@vBq@hC,333333,5&m=59.436884,24.742595,,,C&m=59.437485,24.743150,,,B&m=59.434931,24.745442,,,D&m=59.441293,24.747380,custom:https%3A%2F%2Fdocs.stadiamaps.com%2Fimg%2Fleaf-green.png,,,,-32,-95&markers=59.435561,24.747605,,red,E&size=600x400@2x",[28,3511,3513],{"id":3512},"make-complex-requests-with-ease","Make complex requests with ease",[24,3515,3516],{},"Before today, the Static Maps API was configurable\nvia query string parameters.\nWe occasionally heard from customers having issues though,\nbecause web browsers and servers place limits on URL length.\nThis limited the level of detail and customization.",[24,3518,3519,3520,3524],{},"That’s why we’re now accepting POST requests\nto the ",[35,3521,3523],{"href":3522},"\u002Fblog\u002Fannouncing-cacheable-static-map-images\u002F","cacheable static maps endpoint",".\nPOST parameters are sent via a JSON body,\nmaking it easier to specify complex requests.\nAnd when we add new features—like polygons —\nyou won’t have to worry about URL length.",[24,3526,3527],{},"As far as we know, we’re the first provider to offer this!",[24,3529,3530],{},"Here’s an example request body:",[636,3532,3534],{"className":638,"code":3533,"language":640,"meta":168,"style":168},"{\n  \"center\": \"59.438484,24.742595\",\n  \"size\": \"600x400@2x\",\n  \"zoom\": 14,\n  \"lines\": [\n    {\n      \"shape\": \"oj_kpBkhmen@vFvDlStSdIzN`BxCfMfShA`B~@|AvCrDpG`FfVfRb\\\\zSrBdBhZx\\\\pFdM~BpFn@zAxCrHrH|QjOh_@NtM|Vv@d@aHdHEfD^\\\\DhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG]cEc@{Fm@uF]oDgAwJhAm@vMqGoAs{@dAMfG_@dE_@Ezb@ExWzBBZ?L@|DnTtAqE~CyMp@sB|@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA}@~CVbB`@pDtAN}DxD`AdFi@vBIxBIe@aMuAgPyFwy@{Ca_@yFar@[{C_AsGuAkGqEgY_CmLqAuFuHi[m@vBq@hC\",\n      \"color\": \"333333\",\n      \"width\": 5\n    }\n  ],\n  \"markers\": [\n    {\n      \"lat\": 59.436884,\n      \"lon\": 24.742595\n    },\n    {\n      \"lat\": 59.441293,\n      \"lon\": 24.747380,\n      \"style\": \"custom:https:\u002F\u002Fdocs.stadiamaps.com\u002Fimg\u002Fleaf-green.png\",\n      \"anchor\": [-32, -95]\n    },\n    {\n      \"lat\": 59.435561,\n      \"lon\": 24.747605,\n      \"color\": \"red\",\n      \"label\": \"E\"\n    }\n  ]\n}\n",[349,3535,3536,3540,3552,3564,3576,3584,3589,3617,3629,3639,3644,3649,3656,3660,3672,3682,3687,3691,3702,3713,3725,3744,3749,3754,3766,3778,3790,3801,3806,3812],{"__ignoreMap":168},[644,3537,3538],{"class":646,"line":647},[644,3539,651],{"class":650},[644,3541,3542,3545,3547,3550],{"class":646,"line":172},[644,3543,3544],{"class":656},"  \"center\"",[644,3546,660],{"class":650},[644,3548,3549],{"class":663},"\"59.438484,24.742595\"",[644,3551,437],{"class":650},[644,3553,3554,3557,3559,3562],{"class":646,"line":669},[644,3555,3556],{"class":656},"  \"size\"",[644,3558,660],{"class":650},[644,3560,3561],{"class":663},"\"600x400@2x\"",[644,3563,437],{"class":650},[644,3565,3566,3569,3571,3574],{"class":646,"line":169},[644,3567,3568],{"class":656},"  \"zoom\"",[644,3570,660],{"class":650},[644,3572,3573],{"class":656},"14",[644,3575,437],{"class":650},[644,3577,3578,3581],{"class":646,"line":692},[644,3579,3580],{"class":656},"  \"lines\"",[644,3582,3583],{"class":650},": [\n",[644,3585,3586],{"class":646,"line":755},[644,3587,3588],{"class":650},"    {\n",[644,3590,3591,3594,3596,3599,3602,3605,3607,3610,3612,3615],{"class":646,"line":768},[644,3592,3593],{"class":656},"      \"shape\"",[644,3595,660],{"class":650},[644,3597,3598],{"class":663},"\"oj_kpBkhmen@vFvDlStSdIzN`BxCfMfShA`B~@|AvCrDpG`FfVfRb",[644,3600,3601],{"class":656},"\\\\",[644,3603,3604],{"class":663},"zSrBdBhZx",[644,3606,3601],{"class":656},[644,3608,3609],{"class":663},"pFdM~BpFn@zAxCrHrH|QjOh_@NtM|Vv@d@aHdHEfD^",[644,3611,3601],{"class":656},[644,3613,3614],{"class":663},"DhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG]cEc@{Fm@uF]oDgAwJhAm@vMqGoAs{@dAMfG_@dE_@Ezb@ExWzBBZ?L@|DnTtAqE~CyMp@sB|@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA}@~CVbB`@pDtAN}DxD`AdFi@vBIxBIe@aMuAgPyFwy@{Ca_@yFar@[{C_AsGuAkGqEgY_CmLqAuFuHi[m@vBq@hC\"",[644,3616,437],{"class":650},[644,3618,3619,3622,3624,3627],{"class":646,"line":779},[644,3620,3621],{"class":656},"      \"color\"",[644,3623,660],{"class":650},[644,3625,3626],{"class":663},"\"333333\"",[644,3628,437],{"class":650},[644,3630,3631,3634,3636],{"class":646,"line":1921},[644,3632,3633],{"class":656},"      \"width\"",[644,3635,660],{"class":650},[644,3637,3638],{"class":656},"5\n",[644,3640,3641],{"class":646,"line":1932},[644,3642,3643],{"class":650},"    }\n",[644,3645,3646],{"class":646,"line":1938},[644,3647,3648],{"class":650},"  ],\n",[644,3650,3651,3654],{"class":646,"line":1950},[644,3652,3653],{"class":656},"  \"markers\"",[644,3655,3583],{"class":650},[644,3657,3658],{"class":646,"line":1956},[644,3659,3588],{"class":650},[644,3661,3662,3665,3667,3670],{"class":646,"line":1970},[644,3663,3664],{"class":656},"      \"lat\"",[644,3666,660],{"class":650},[644,3668,3669],{"class":656},"59.436884",[644,3671,437],{"class":650},[644,3673,3674,3677,3679],{"class":646,"line":1983},[644,3675,3676],{"class":656},"      \"lon\"",[644,3678,660],{"class":650},[644,3680,3681],{"class":656},"24.742595\n",[644,3683,3684],{"class":646,"line":1996},[644,3685,3686],{"class":650},"    },\n",[644,3688,3689],{"class":646,"line":2007},[644,3690,3588],{"class":650},[644,3692,3693,3695,3697,3700],{"class":646,"line":2016},[644,3694,3664],{"class":656},[644,3696,660],{"class":650},[644,3698,3699],{"class":656},"59.441293",[644,3701,437],{"class":650},[644,3703,3704,3706,3708,3711],{"class":646,"line":2030},[644,3705,3676],{"class":656},[644,3707,660],{"class":650},[644,3709,3710],{"class":656},"24.747380",[644,3712,437],{"class":650},[644,3714,3715,3718,3720,3723],{"class":646,"line":2039},[644,3716,3717],{"class":656},"      \"style\"",[644,3719,660],{"class":650},[644,3721,3722],{"class":663},"\"custom:https:\u002F\u002Fdocs.stadiamaps.com\u002Fimg\u002Fleaf-green.png\"",[644,3724,437],{"class":650},[644,3726,3727,3730,3733,3736,3738,3741],{"class":646,"line":2044},[644,3728,3729],{"class":656},"      \"anchor\"",[644,3731,3732],{"class":650},": [",[644,3734,3735],{"class":656},"-32",[644,3737,352],{"class":650},[644,3739,3740],{"class":656},"-95",[644,3742,3743],{"class":650},"]\n",[644,3745,3747],{"class":646,"line":3746},22,[644,3748,3686],{"class":650},[644,3750,3752],{"class":646,"line":3751},23,[644,3753,3588],{"class":650},[644,3755,3757,3759,3761,3764],{"class":646,"line":3756},24,[644,3758,3664],{"class":656},[644,3760,660],{"class":650},[644,3762,3763],{"class":656},"59.435561",[644,3765,437],{"class":650},[644,3767,3769,3771,3773,3776],{"class":646,"line":3768},25,[644,3770,3676],{"class":656},[644,3772,660],{"class":650},[644,3774,3775],{"class":656},"24.747605",[644,3777,437],{"class":650},[644,3779,3781,3783,3785,3788],{"class":646,"line":3780},26,[644,3782,3621],{"class":656},[644,3784,660],{"class":650},[644,3786,3787],{"class":663},"\"red\"",[644,3789,437],{"class":650},[644,3791,3793,3796,3798],{"class":646,"line":3792},27,[644,3794,3795],{"class":656},"      \"label\"",[644,3797,660],{"class":650},[644,3799,3800],{"class":663},"\"E\"\n",[644,3802,3804],{"class":646,"line":3803},28,[644,3805,3643],{"class":650},[644,3807,3809],{"class":646,"line":3808},29,[644,3810,3811],{"class":650},"  ]\n",[644,3813,3815],{"class":646,"line":3814},30,[644,3816,695],{"class":650},[28,3818,3820],{"id":3819},"were-not-stopping-here","We’re not stopping here!",[24,3822,3823],{},"Our roadmap still has more features on it (thanks to you!).\nKeep an eye out for integration with our routing API,\npolygon drawing, and more—all in a single API call.",[28,3825,3827],{"id":3826},"accessing-the-new-functionality","Accessing the new functionality",[24,3829,3830,3831,3835,3836,458],{},"We’ve updated our ",[35,3832,165],{"href":3833,"rel":3834,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fstatic-maps\u002F?utm_campaign=custom_markers_post&utm_medium=owned&utm_source=marketing_site",[39],"\nwith everything you need to get started,\nincluding HTML and cURL examples.\nAnd if you have any questions, you’re just an email away from real human support.\nDrop us a note at ",[35,3837,3839],{"href":3838},"mailto:support@stadiamaps.com","support@stadiamaps.com",[852,3841,854],{},{"title":168,"searchDepth":169,"depth":169,"links":3843},[3844,3845,3846,3847],{"id":3493,"depth":172,"text":3494},{"id":3512,"depth":172,"text":3513},{"id":3819,"depth":172,"text":3820},{"id":3826,"depth":172,"text":3827},"Enhance your static maps with custom marker images, and bypass the URL length limit with POST requests.",[3850,3851,3852,1289],"Static Maps","Custom Markers","Map Images",{},"\u002Fblog\u002Fcustom-markers-in-static-map-images","2024-05-14","---\ndescription: >-\n  Enhance your static maps with custom marker images,\n  and bypass the URL length limit with POST requests.\npublished: 2024-05-14\nkeywords:\n  - Static Maps\n  - Custom Markers\n  - Map Images\n  - API Update\n---\n\n# Custom markers and POST support for Static Maps\n\nStatic Maps are the fastest ways to add maps to your website or app.\nSince each map is a single PNG or JPEG,\nthey are a lot easier to set up than interactive maps.\nYou can even add markers and lines to static maps&mdash;our servers handle the hard work.\n\n## Custom marker images\n\nToday you can add markers to a static map by including the coordinates in your request.\nWe’ll automatically select a suitable image based on the map style.\nYou can also use a labeled marker with a classic solid design for differentiation.\n\nToday, we’re letting you go even further with branding and improved differentiation.\nJust send us the image URL in your request to customize the marker image!\nThis feature is now available on all plans that have access to static maps\n(including free trials).\n\nWe’re launching with support for up to 5 custom marker images per request,\ngiving you plenty of flexibility.\nAnd the images can be up to 128px in each dimension,\nso your carefully designed icons will look great on retina and other HiDPI screens.\n\n![Static Map](https:\u002F\u002Ftiles.stadiamaps.com\u002Fstatic\u002Falidade_smooth.png?center=59.438484,24.742595&zoom=14&l=oj_kpBkhmen@vFvDlStSdIzN`BxCfMfShA`B~@|AvCrDpG`FfVfRb\\zSrBdBhZx\\pFdM~BpFn@zAxCrHrH|QjOh_@NtM|Vv@d@aHdHEfD^\\DhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG]cEc@{Fm@uF]oDgAwJhAm@vMqGoAs{@dAMfG_@dE_@Ezb@ExWzBBZ?L@|DnTtAqE~CyMp@sB|@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA}@~CVbB`@pDtAN}DxD`AdFi@vBIxBIe@aMuAgPyFwy@{Ca_@yFar@[{C_AsGuAkGqEgY_CmLqAuFuHi[m@vBq@hC,333333,5&m=59.436884,24.742595,,,C&m=59.437485,24.743150,,,B&m=59.434931,24.745442,,,D&m=59.441293,24.747380,custom:https%3A%2F%2Fdocs.stadiamaps.com%2Fimg%2Fleaf-green.png,,,,-32,-95&markers=59.435561,24.747605,,red,E&size=600x400@2x)\n\n## Make complex requests with ease\n\nBefore today, the Static Maps API was configurable\nvia query string parameters.\nWe occasionally heard from customers having issues though,\nbecause web browsers and servers place limits on URL length.\nThis limited the level of detail and customization.\n\nThat’s why we’re now accepting POST requests\nto the [cacheable static maps endpoint](\u002Fblog\u002Fannouncing-cacheable-static-map-images\u002F).\nPOST parameters are sent via a JSON body,\nmaking it easier to specify complex requests.\nAnd when we add new features&mdash;like polygons &mdash;\nyou won’t have to worry about URL length.\n\nAs far as we know, we’re the first provider to offer this!\n\nHere’s an example request body:\n\n```json\n{\n  \"center\": \"59.438484,24.742595\",\n  \"size\": \"600x400@2x\",\n  \"zoom\": 14,\n  \"lines\": [\n    {\n      \"shape\": \"oj_kpBkhmen@vFvDlStSdIzN`BxCfMfShA`B~@|AvCrDpG`FfVfRb\\\\zSrBdBhZx\\\\pFdM~BpFn@zAxCrHrH|QjOh_@NtM|Vv@d@aHdHEfD^\\\\DhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG]cEc@{Fm@uF]oDgAwJhAm@vMqGoAs{@dAMfG_@dE_@Ezb@ExWzBBZ?L@|DnTtAqE~CyMp@sB|@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA}@~CVbB`@pDtAN}DxD`AdFi@vBIxBIe@aMuAgPyFwy@{Ca_@yFar@[{C_AsGuAkGqEgY_CmLqAuFuHi[m@vBq@hC\",\n      \"color\": \"333333\",\n      \"width\": 5\n    }\n  ],\n  \"markers\": [\n    {\n      \"lat\": 59.436884,\n      \"lon\": 24.742595\n    },\n    {\n      \"lat\": 59.441293,\n      \"lon\": 24.747380,\n      \"style\": \"custom:https:\u002F\u002Fdocs.stadiamaps.com\u002Fimg\u002Fleaf-green.png\",\n      \"anchor\": [-32, -95]\n    },\n    {\n      \"lat\": 59.435561,\n      \"lon\": 24.747605,\n      \"color\": \"red\",\n      \"label\": \"E\"\n    }\n  ]\n}\n```\n\n## We’re not stopping here!\n\nOur roadmap still has more features on it (thanks to you!).\nKeep an eye out for integration with our routing API,\npolygon drawing, and more&mdash;all in a single API call.\n\n## Accessing the new functionality\n\nWe’ve updated our [documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fstatic-maps\u002F?utm_campaign=custom_markers_post&utm_medium=owned&utm_source=marketing_site)\nwith everything you need to get started,\nincluding HTML and cURL examples.\nAnd if you have any questions, you’re just an email away from real human support.\nDrop us a note at [support@stadiamaps.com](mailto:support@stadiamaps.com).\n",{"title":3482,"description":3848},"blog\u002Fcustom-markers-in-static-map-images","8r3elZWFWvGVnLxEhRNPX9PR2Cd8DFjAqw-5ePC2M8I",{"id":3861,"title":3862,"abstract":7,"author":7,"body":3863,"description":3933,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":3934,"meta":3935,"modified":7,"navigation":187,"path":3936,"proficiencyLevel":7,"published":3937,"rawbody":3938,"schemaOrg":7,"schemaType":7,"seo":3939,"stem":3940,"__hash__":3941},"blog\u002Fblog\u002F2024-satellite-imagery-refresh.md","2024 Satellite Imagery Map Refresh",{"type":14,"value":3864,"toc":3925},[3865,3868,3871,3874,3876,3880,3883,3886,3889,3893,3896,3900,3903,3905,3908,3910,3913],[17,3866,3862],{"id":3867},"_2024-satellite-imagery-map-refresh",[24,3869,3870],{},"Today, Stadia Maps unveils significant enhancements to our Alidade Satellite style and other imagery offerings. This\nrefresh brings vibrant global color, expands 50cm resolution coverage, introduces 30cm high-resolution imagery in major\ncities, and refreshes imagery across our entire map portfolio.",[24,3872,3873],{},"People use imagery maps every day to understand a location in its “true” visual context: hikers verify trails in\nstunning clarity, families find their next home—with a porch and lots of trees for the summer, and travelers plan their\nvacation surroundings in vivid detail. Our latest improvements mean your visual context is not just updated—it's richer,\nclearer, and more precise.",[215,3875],{":center":1544,":scroll-zoom":218,":use-search":218,":use-theme-switcher":219,":zoom":1545,"id":221,"style":222,"theme":223},[28,3877,3879],{"id":3878},"a-sharper-world-enhanced-imagery","A Sharper World: Enhanced Imagery",[24,3881,3882],{},"When we first rolled out our imagery maps last year, we were determined to provide a solid baseline level of detail. We\nstarted off with a mix of 1.5m resolution (zoom level 16) for the whole world, and then added 50cm resolution (zoom\nlevel 18) over about 23 million square kilometers. Now, we're stepping it up by including an additional 4 million square\nkilometers of 50cm imagery. This update means you get to see more of the world in better detail, from bustling city\ncorners to the quietest, most remote spots.",[24,3884,3885],{},"But why stop there? On top of that, we've added over a quarter million square kilometers of 30cm resolution imagery,\nbringing things into even sharper focus at zoom level 19 and above. It’s just the beginning – we're on a mission to keep\nboosting our maps with even higher resolution imagery.",[24,3887,3888],{},"All in all, with nearly 5 million square kilometers of improved imagery, there's a lot more for us to explore and enjoy.\nWhether you're planning a hike, finding your next home, or just curious about a new place, the world just got a bit\ncloser to your fingertips.",[28,3890,3892],{"id":3891},"vivid-colors-fresh-views","Vivid Colors & Fresh Views",[24,3894,3895],{},"In imagery maps resolution matters, but the magic really happens in the details—the colors, the clarity, and the\nfreshness of an image. That's why this update isn't just about adding more pixels; it's about making every pixel count.",[1205,3897,3899],{"id":3898},"consistency-is-key","Consistency is key.",[24,3901,3902],{},"We've made the colors across all zoom levels more consistent, ensuring that no matter how far in or out you're zooming,\nthe experience remains seamless. This means better data overlays and a smoother experience for everyone. At higher zoom\nlevels, we've continued to prefer “true colors” that showcase the unique beauty of each location, balancing regional\nflair with a cohesive global palette.",[1205,3904,1559],{"id":1558},[24,3906,3907],{},"We're dedicated to keeping our imagery as fresh and current as possible. This update phases out our oldest imagery—some\ndating back to 2019—with updated imagery. Our oldest imagery is now only a couple of years old. While it isn’t possible\nto keep an imagery map as up-to-date as we do our street maps, we will keep updating pixels all the time, because the\nfresher the imagery, the higher the quality of the map you get to explore.",[28,3909,1566],{"id":1565},[24,3911,3912],{},"You can get started with our imagery basemap today. Sign up for the new Standard or Professional plan, and turn the\nearth into your canvas today.",[56,3914,3915,3921],{},[59,3916,3917],{},[35,3918,1605],{"href":3919,"rel":3920,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fmap-styles\u002Falidade-satellite\u002F?utm_source=marketing_site&utm_campaign=2024_satellite_refresh&utm_content=get_started_satellite",[39],[59,3922,3923],{},[35,3924,1611],{"href":1610},{"title":168,"searchDepth":169,"depth":169,"links":3926},[3927,3928,3932],{"id":3878,"depth":172,"text":3879},{"id":3891,"depth":172,"text":3892,"children":3929},[3930,3931],{"id":3898,"depth":669,"text":3899},{"id":1558,"depth":669,"text":1559},{"id":1565,"depth":172,"text":1566},"The 2024 imagery refresh brings vibrant global color, expands 50cm resolution coverage, introduces 30cm high-resolution  imagery in major cities, and refreshes imagery across our entire map portfolio.",[283,284,285,286,212],{},"\u002Fblog\u002F2024-satellite-imagery-refresh","2024-04-12","---\ndescription: >-\n  The 2024 imagery refresh brings vibrant global color, expands 50cm resolution coverage, introduces 30cm high-resolution \n  imagery in major cities, and refreshes imagery across our entire map portfolio.\npublished: 2024-04-12\nkeywords:\n  - Satellite Imagery\n  - Aerial Photography\n  - Map Update\n  - High Resolution\n  - Alidade Satellite\n---\n\n# 2024 Satellite Imagery Map Refresh\n\nToday, Stadia Maps unveils significant enhancements to our Alidade Satellite style and other imagery offerings. This\nrefresh brings vibrant global color, expands 50cm resolution coverage, introduces 30cm high-resolution imagery in major\ncities, and refreshes imagery across our entire map portfolio.\n\nPeople use imagery maps every day to understand a location in its “true” visual context: hikers verify trails in\nstunning clarity, families find their next home—with a porch and lots of trees for the summer, and travelers plan their\nvacation surroundings in vivid detail. Our latest improvements mean your visual context is not just updated—it's richer,\nclearer, and more precise.\n\n::cross-platform-map{id=\"map\" style=\"height: 400px;\"}\n---\ncenter: [172, -43.2]\nscroll-zoom: true\nzoom: 7\ntheme: alidade_satellite\nuse-theme-switcher: false\nuse-search: true\n---\n::\n\n## A Sharper World: Enhanced Imagery\n\nWhen we first rolled out our imagery maps last year, we were determined to provide a solid baseline level of detail. We\nstarted off with a mix of 1.5m resolution (zoom level 16) for the whole world, and then added 50cm resolution (zoom\nlevel 18) over about 23 million square kilometers. Now, we're stepping it up by including an additional 4 million square\nkilometers of 50cm imagery. This update means you get to see more of the world in better detail, from bustling city\ncorners to the quietest, most remote spots.\n\nBut why stop there? On top of that, we've added over a quarter million square kilometers of 30cm resolution imagery,\nbringing things into even sharper focus at zoom level 19 and above. It’s just the beginning – we're on a mission to keep\nboosting our maps with even higher resolution imagery.\n\nAll in all, with nearly 5 million square kilometers of improved imagery, there's a lot more for us to explore and enjoy.\nWhether you're planning a hike, finding your next home, or just curious about a new place, the world just got a bit\ncloser to your fingertips.\n\n## Vivid Colors & Fresh Views\n\nIn imagery maps resolution matters, but the magic really happens in the details—the colors, the clarity, and the\nfreshness of an image. That's why this update isn't just about adding more pixels; it's about making every pixel count.\n\n### Consistency is key.\n\nWe've made the colors across all zoom levels more consistent, ensuring that no matter how far in or out you're zooming,\nthe experience remains seamless. This means better data overlays and a smoother experience for everyone. At higher zoom\nlevels, we've continued to prefer “true colors” that showcase the unique beauty of each location, balancing regional\nflair with a cohesive global palette.\n\n### Keeping Things Fresh\n\nWe're dedicated to keeping our imagery as fresh and current as possible. This update phases out our oldest imagery—some\ndating back to 2019—with updated imagery. Our oldest imagery is now only a couple of years old. While it isn’t possible\nto keep an imagery map as up-to-date as we do our street maps, we will keep updating pixels all the time, because the\nfresher the imagery, the higher the quality of the map you get to explore.\n\n## Next Steps\n\nYou can get started with our imagery basemap today. Sign up for the new Standard or Professional plan, and turn the \nearth into your canvas today.\n\n* [Get started in MapLibre, Leaflet, OpenLayers or just about any other mapping library!](https:\u002F\u002Fdocs.stadiamaps.com\u002Fmap-styles\u002Falidade-satellite\u002F?utm_source=marketing_site&utm_campaign=2024_satellite_refresh&utm_content=get_started_satellite)\n* [Explore the new imagery](\u002Fexplore-the-map\u002F#style=alidade_satellite)\n",{"title":3862,"description":3933},"blog\u002F2024-satellite-imagery-refresh","8nxeKlg7_w5Anfqayd1vWGdhGf1yM7QEtyhCHsXdezU",{"id":3943,"title":3944,"abstract":7,"author":7,"body":3945,"description":4014,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":4015,"meta":4018,"modified":7,"navigation":187,"path":4019,"proficiencyLevel":7,"published":4020,"rawbody":4021,"schemaOrg":7,"schemaType":7,"seo":4022,"stem":4023,"__hash__":4024},"blog\u002Fblog\u002Fannouncing-cacheable-static-map-images.md","Announcing Cacheable Static Maps",{"type":14,"value":3946,"toc":4009},[3947,3950,3953,3957,3960,3964,3967,3970,3983,3987],[17,3948,3944],{"id":3949},"announcing-cacheable-static-maps",[24,3951,3952],{},"Our Static Maps API offers an easy way to add maps to your website or app.\nIf your use case doesn't require interactive maps,\nyou can push all the rendering complexity to our servers.\nWe'll even let you customize the maps with annotations like markers and lines,\nall using a simple URL!",[28,3954,3956],{"id":3955},"simpler-licensing-for-printing-and-caching","Simpler Licensing for Printing and Caching",[24,3958,3959],{},"Today, we're launching a cacheable static maps endpoint with special terms to enable new use cases.\nFor digital use, this endpoint allows storing or caching map images in your infrastructure or an image CDN\n(as long as you maintain a paid subscription).\nFor print applications, you'll no longer need to contact us for a custom license if your usage meets certain conditions.\nWith these two changes, we're making it easier for you to build solutions without having to ask us for custom pricing or terms.",[28,3961,3963],{"id":3962},"advanced-privacy-protection-enhanced-customizing-performance","Advanced Privacy Protection; Enhanced Customizing & Performance",[24,3965,3966],{},"The new digital use terms allow you to create solutions using static maps so end-user traffic never goes to our servers.\nIf you're looking for a way to enhance end-user privacy beyond our no-tracking policy,\nor have particularly strict compliance needs,\nthe new endpoint enables you to pre-generate or cache images fully under your control.",[24,3968,3969],{},"For users looking to utilize popular image CDNs or push-based deployment strategies used by some site generators,\nthis new endpoint allows you to take advantage of these enhancements and remain compliant with our terms.",[24,3971,3972,3973,3977,3978,458],{},"Cacheable static maps are available using a new endpoint,\nwhich you can read about in our ",[35,3974,165],{"href":3975,"rel":3976,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fstatic-maps\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=static_maps&utm_content=cacheable_static_announcement",[39],".\nThe request parameters are the same as our existing static endpoint,\nso the migration only takes a few seconds.\nWe can't offer caching on the Alidade Satellite style at this time,\nbut all other features and capabilities are identical,\nincluding access to the ",[35,3979,3982],{"href":3980,"rel":3981,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fthemes\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=static_maps&utm_content=cacheable_static_announcement#stadia-stamen",[39],"map styles from Stamen Design",[28,3984,3986],{"id":3985},"learn-more","Learn more",[56,3988,3989,3996,4003],{},[59,3990,3991,3992,458],{},"Learn how to use the new endpoint from our ",[35,3993,3995],{"href":3975,"rel":3994,"target":40},[39],"static maps documentation",[59,3997,3998,3999,4002],{},"See our ",[35,4000,4001],{"href":148},"pricing"," for cacheable static maps and all other endpoints.",[59,4004,3427,4005,458],{},[35,4006,4008],{"href":4007},"\u002Fterms-of-service\u002F#cacheable-terms","terms for the new endpoint",{"title":168,"searchDepth":169,"depth":169,"links":4010},[4011,4012,4013],{"id":3955,"depth":172,"text":3956},{"id":3962,"depth":172,"text":3963},{"id":3985,"depth":172,"text":3986},"Cache your static maps for digital or print use with our new endpoint.",[3850,4016,4017,1289],"Caching","Print Maps",{},"\u002Fblog\u002Fannouncing-cacheable-static-map-images","2024-03-26","---\ndescription: \"Cache your static maps for digital or print use with our new endpoint.\"\npublished: 2024-03-26\nkeywords:\n  - Static Maps\n  - Caching\n  - Print Maps\n  - API Update\n---\n\n# Announcing Cacheable Static Maps\n\nOur Static Maps API offers an easy way to add maps to your website or app. \nIf your use case doesn't require interactive maps,\nyou can push all the rendering complexity to our servers.\nWe'll even let you customize the maps with annotations like markers and lines,\nall using a simple URL!\n\n## Simpler Licensing for Printing and Caching\n\nToday, we're launching a cacheable static maps endpoint with special terms to enable new use cases.\nFor digital use, this endpoint allows storing or caching map images in your infrastructure or an image CDN \n(as long as you maintain a paid subscription).\nFor print applications, you'll no longer need to contact us for a custom license if your usage meets certain conditions.\nWith these two changes, we're making it easier for you to build solutions without having to ask us for custom pricing or terms.\n\n## Advanced Privacy Protection; Enhanced Customizing & Performance\n\nThe new digital use terms allow you to create solutions using static maps so end-user traffic never goes to our servers.\nIf you're looking for a way to enhance end-user privacy beyond our no-tracking policy,\nor have particularly strict compliance needs,\nthe new endpoint enables you to pre-generate or cache images fully under your control.\n\nFor users looking to utilize popular image CDNs or push-based deployment strategies used by some site generators,\nthis new endpoint allows you to take advantage of these enhancements and remain compliant with our terms.\n\nCacheable static maps are available using a new endpoint,\nwhich you can read about in our [documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fstatic-maps\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=static_maps&utm_content=cacheable_static_announcement){ target=\"_blank\" }.\nThe request parameters are the same as our existing static endpoint,\nso the migration only takes a few seconds.\nWe can't offer caching on the Alidade Satellite style at this time,\nbut all other features and capabilities are identical,\nincluding access to the [map styles from Stamen Design](https:\u002F\u002Fdocs.stadiamaps.com\u002Fthemes\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=static_maps&utm_content=cacheable_static_announcement#stadia-stamen){ target=\"_blank\" }.\n\n## Learn more\n\n* Learn how to use the new endpoint from our [static maps documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fstatic-maps\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=static_maps&utm_content=cacheable_static_announcement){ target=\"_blank\" }.\n* See our [pricing](\u002Fpricing\u002F) for cacheable static maps and all other endpoints.\n* Read our [terms for the new endpoint](\u002Fterms-of-service\u002F#cacheable-terms).\n",{"title":3944,"description":4014},"blog\u002Fannouncing-cacheable-static-map-images","elij7wiHUwnaQavS6sAgHkEOsDqoh7loxujxVggd2zg",{"id":4026,"title":4027,"abstract":7,"author":7,"body":4028,"description":4093,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":4094,"meta":4098,"modified":7,"navigation":187,"path":4099,"proficiencyLevel":7,"published":4100,"rawbody":4101,"schemaOrg":7,"schemaType":7,"seo":4102,"stem":4103,"__hash__":4104},"blog\u002Fblog\u002Fannouncing-version-2-of official-sdks.md","Announcing Version 2 of our Official SDKs",{"type":14,"value":4029,"toc":4091},[4030,4033,4036,4039,4058,4061],[17,4031,4027],{"id":4032},"announcing-version-2-of-our-official-sdks",[24,4034,4035],{},"Today marks a new milestone in the lifecycle of the Stadia Maps official SDKs.\nWe have just released version 2.0.0 of our API client libraries\nfor the web, mobile and backend.\nWith official clients in TypeScript, Swift, Kotlin, and Python,\nwe've already helped thousands of developers get started in just a few lines of code.",[24,4037,4038],{},"This release includes a number of improvements:",[56,4040,4041,4044,4047,4055],{},[59,4042,4043],{},"A factor for adjusting the cost of alleys when doing automobile routing",[59,4045,4046],{},"A resample distance parameter for elevation requests, which makes it even easier to get elevation profiles; just give us a simple set of points and we'll interpolate the rest!",[59,4048,4049,4050,4054],{},"Support for requesting one or more alternate routes (great for ",[35,4051,4053],{"href":4052},"\u002Fproducts\u002Frouting-navigation","navigation applications",")",[59,4056,4057],{},"Additional options to ignore restrictions (particularly useful during map matching when you just want to know which roads a vehicle traversed)",[24,4059,4060],{},"If you're using one of our existing libraries already,\nit will generally keep on working as-is.\nHowever, in order to make a few of the improvements,\nwe had to introduce backwards-incompatible changes,\nwhich is why it gets a major version bump.\nFor migration instructions, refer to the release notes lined below:",[56,4062,4063,4070,4077,4084],{},[59,4064,4065],{},[35,4066,4069],{"href":4067,"rel":4068,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-ts\u002Freleases\u002Ftag\u002Fv2.0.0",[39],"TypeScript",[59,4071,4072],{},[35,4073,4076],{"href":4074,"rel":4075,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-swift\u002Freleases\u002Ftag\u002F2.0.0",[39],"Swift",[59,4078,4079],{},[35,4080,4083],{"href":4081,"rel":4082,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-kotlin\u002Freleases\u002Ftag\u002Fv2.0.0",[39],"Kotlin",[59,4085,4086],{},[35,4087,4090],{"href":4088,"rel":4089,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-py\u002Freleases\u002Ftag\u002Fv2.0.0",[39],"Python",{"title":168,"searchDepth":169,"depth":169,"links":4092},[],"We've added new routing and elevation API features in our latest SDK releases.",[4095,3472,179,4096,4097],"SDK","Elevation","Release",{},"\u002Fblog\u002Fannouncing-version-2-of-official-sdks","2024-03-20","---\ndescription: \"We've added new routing and elevation API features in our latest SDK releases.\"\npublished: 2024-03-20\nkeywords:\n  - SDK\n  - API Client\n  - Routing\n  - Elevation\n  - Release\n---\n\n# Announcing Version 2 of our Official SDKs\n\nToday marks a new milestone in the lifecycle of the Stadia Maps official SDKs.\nWe have just released version 2.0.0 of our API client libraries\nfor the web, mobile and backend.\nWith official clients in TypeScript, Swift, Kotlin, and Python,\nwe've already helped thousands of developers get started in just a few lines of code.\n\nThis release includes a number of improvements:\n\n* A factor for adjusting the cost of alleys when doing automobile routing\n* A resample distance parameter for elevation requests, which makes it even easier to get elevation profiles; just give us a simple set of points and we'll interpolate the rest!\n* Support for requesting one or more alternate routes (great for [navigation applications](\u002Fproducts\u002Frouting-navigation))\n* Additional options to ignore restrictions (particularly useful during map matching when you just want to know which roads a vehicle traversed)\n\nIf you're using one of our existing libraries already,\nit will generally keep on working as-is.\nHowever, in order to make a few of the improvements,\nwe had to introduce backwards-incompatible changes,\nwhich is why it gets a major version bump.\nFor migration instructions, refer to the release notes lined below:\n\n* [TypeScript](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-ts\u002Freleases\u002Ftag\u002Fv2.0.0)\n* [Swift](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-swift\u002Freleases\u002Ftag\u002F2.0.0)\n* [Kotlin](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-kotlin\u002Freleases\u002Ftag\u002Fv2.0.0)\n* [Python](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-py\u002Freleases\u002Ftag\u002Fv2.0.0)\n",{"title":4027,"description":4093},"blog\u002Fannouncing-version-2-of official-sdks","FrANzsGEBBa5_czuy10G_E5nuzEIKQECpfP5d_Wqdys",{"id":4106,"title":4107,"abstract":7,"author":7,"body":4108,"description":6177,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":6178,"meta":6180,"modified":7,"navigation":187,"path":1788,"proficiencyLevel":872,"published":6182,"rawbody":6183,"schemaOrg":7,"schemaType":875,"seo":6184,"stem":6185,"__hash__":6186},"blog\u002Fblog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-1.md","Ferrostar: Building a Cross-Platform Navigation SDK in Rust (Part 1)",{"type":14,"value":4109,"toc":6159},[4110,4113,4116,4119,4123,4133,4136,4143,4147,4150,4153,4164,4167,4170,4200,4204,4207,4216,4219,4222,4233,4239,4243,4250,4263,4267,4270,4286,4294,4301,4379,4394,4423,4434,4470,4491,4519,4598,4602,4605,4611,4616,4623,4701,4729,4732,4736,4743,4758,4856,4859,4866,4962,4966,4969,4972,5450,5460,5478,5504,5508,5511,5601,5622,5625,5687,5693,5726,5732,5736,5739,5831,5846,5859,5933,5943,6044,6054,6065,6068,6072,6078,6085,6094,6097,6101,6104,6121,6131,6134,6136,6144,6147,6156],[17,4111,4107],{"id":4112},"ferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-1",[24,4114,4115],{},"This is the first in a series of technical blog posts\ncovering the joys and challenges\nof building a cross-platform shared library,\nwith a focus on use in mobile applications.",[24,4117,4118],{},"As a motivating example to frame things,\nwe'll follow the journey of building Ferrostar,\na free and open-source navigation SDK.\nWe want to offer a modern SDK that is cross-platform,\nvendor-neutral, and easily extensible\nboth by direct contributors and developers using it in their apps.",[28,4120,4122],{"id":4121},"why","Why?",[24,4124,4125,4126,4128,4129,4132],{},"Before we get into the technical weeds too much,\nit's worth taking a moment to ask ",[611,4127,4121],{},".\nAt Stadia Maps,\nwe have offered ",[35,4130,4131],{"href":45},"highly customizable routing","\nsince 2017,\nand support use cases including safe pedestrian routing through lit areas,\ngolf cart routing that prefers multi-use paths,\nand more!\nBut developers are on their own\nwhen it comes to offering a turn-by-turn navigation UI.\nSeveral open-source apps already offer navigation,\nbut the solution is not generalized.\nAmong open-source navigation SDKs,\nMapLibre Navigation Android being the most mature at the time of this writing.\nBut as the name suggests, it is Android-specific.\nAnd since the internals originally came from old open-source Mapbox code,\nit takes considerable effort to use with other vendors,\nand extensibility was never a core design consideration.",[24,4134,4135],{},"Starting a new navigation SDK is certainly an ambitious project,\nbut at the moment there is no navigation SDK that is\nhigh-quality, cross-platform, and open-source.\nWe're here to change that,\nand enable developers to bring these routing innovations to their users.",[24,4137,4138,4139,458],{},"This post series is about the nuts and bolts of how we plan to pull it off.\nWe'll start with an overview of ways to share common logic across platforms,\nexplain the architecture we settled on,\nand finish with a deep dive into the first technical topic:\nbinding generation with ",[35,4140,2307],{"href":4141,"rel":4142,"target":40},"https:\u002F\u002Fmozilla.github.io\u002Funiffi-rs\u002F",[39],[28,4144,4146],{"id":4145},"how-to-share-common-logic","How to Share Common Logic?",[24,4148,4149],{},"We want to target multiple platforms: iOS and Android for starters.\nCertain code is the same regardless of where you're running it.\nAlgorithms like detecting if the user has strayed off the route\nand calculating the distance to the next turn\nshould be written once and shared across platforms.\nAnd at an even higher level,\nthe broad \"business logic\" of a turn-by-turn navigation experience\nshould be common shared code.",[24,4151,4152],{},"Broadly speaking, there are two common approaches\nfor sharing code across platforms in mobile apps today.\nFirst, there are cross-platform app development frameworks like\nFlutter, React Native, or Kotlin Multiplatform.\nThey promise the ability to write your business logic and UI once\nand run it anywhere.\nThe second approach is to put your business logic in a shared library.\nYou write your code in a reasonably portable language (usually C++)\nand link this with your (platform-specific) applications.",[24,4154,4155,4156,4159,4160,4163],{},"In general,\nthe cross-platform frameworks are optimized for building ",[611,4157,4158],{},"applications",",\nnot ",[611,4161,4162],{},"libraries",".\nWe want to ensure that we can support additional platforms\nwith relative ease.\nYou can't just pick up React Native, for example,\nand run it on a bicycle computer.\nThis is situation is improving though.\nFor example, Flutter now runs on certain embedded devices,\nand Kotlin Multiplatform has a quickly improving support for library targets.\nHowever, these are still very early stage developments,\nand they involve a certain amount of ecosystem lock-in.",[24,4165,4166],{},"Given our requirements, we opted for the shared library approach.\nHistorically, C++ has been a popular choice for the task.\nIt is portable across a wide range of platforms,\ncan be made to interoperate with almost any other language,\nand usually produces small, well-optimized binaries.\nWe preferred to use something else for a few reasons,\nthe most important being\nthat it is difficult to write safe and correct C++ code,\nespecially as a new contributor.",[24,4168,4169],{},"At Stadia Maps, we have been shipping Rust in production since 2018.\nOur investment has rewarded us with\nconsistently good performance (Rust is keen on zero-cost abstractions),\nmemory safety,\nand excellent maintainability.\nAnd Rust code tends to have fewer bugs as well!\nRust also has excellent interoperability with other languages\nvia a straightforward FFI using the platform's C ABI,\nin stark contrast to C++ which can be rather complex to interface with.\nRust also has a large and growing list of supported platforms,\nincluding iOS and Android on several architectures.",[24,4171,4172,4173,437,4178,453,4183,4188,4189,2616,4194,4199],{},"We aren't alone in our selection of Rust either.\nWe've seen a lot of exciting development in Rust mobile frameworks\nlike ",[35,4174,4177],{"href":4175,"rel":4176,"target":40},"https:\u002F\u002Fredbadger.github.io\u002Fcrux\u002F",[39],"Crux",[35,4179,4182],{"href":4180,"rel":4181,"target":40},"https:\u002F\u002Fdioxuslabs.com\u002F",[39],"Dioxus",[35,4184,4187],{"href":4185,"rel":4186,"target":40},"https:\u002F\u002Fgithub.com\u002Fcunarist\u002Frinf",[39],"Rinf"," over the past year.\nBut it's not just new experimental projects that are adopting Rust.\nWe know that both ",[35,4190,4193],{"href":4191,"rel":4192,"target":40},"https:\u002F\u002Fwiki.mozilla.org\u002FOxidation",[39],"Mozilla",[35,4195,4198],{"href":4196,"rel":4197,"target":40},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=e2ID05dpJzo",[39],"Lyft","\nare using Rust shared libraries in their mobile apps.\nRust is already being used in production mobile apps today.",[28,4201,4203],{"id":4202},"architecture-overview","Architecture Overview",[24,4205,4206],{},"Zooming out, let's look at the broader architecture we adopted.\nThe core is the place where we want all shared logic to live.\nIn the context of our navigation SDK,\nthis includes parsing API responses,\nfiguring out when to advance navigation to the next step,\ncalculating the distance to the next turn,\nand so on.",[24,4208,4209,4210,2686,4213,458],{},"Shared logic in a \"functional core\" isn't new,\nbut we can go one step further and define our data models too!\nThis lets us keep the navigation logic vendor- and platform-agnostic.\nFor example,\nwe define a common location update type with fields like\ncoordinate, timestamp, and heading.\nThis way the core logic doesn't need to care about the differences between\n",[349,4211,4212],{},"CLLocation",[349,4214,4215],{},"android.location.Location",[24,4217,4218],{},"We're building a Rust library that's callable via the C ABI.\nBut if we want any mobile devs to even try our framework,\nwe'll need to expose a nicer Swift\u002FKotlin interface.\nThese are called bindings,\nand they provide a thin layer that hides the messy details\nof going back and forth between Rust and the \"native\" mobile code.",[24,4220,4221],{},"Finally, we have the native mobile library.\nThis is the only thing that most app developers will see,\nand it handles communications with the \"outside world\" (ex: internet and GPS),\nand provides a higher level API that can be a bit more \"opinionated.\"\nWe won't say much more about this layer in the rest of our discussions,\nas many volumes have been written on good API and library design.",[24,4223,4224,4227,4228,4232],{},[62,4225,4226],{},"Spoiler to avert anxiety and frantic typing",": the rest of this blog goes deep into\n\"how the sausage is made.\"\nTo save you the tedious work of reproducing the structure for your next library,\nwe've put together a ",[35,4229,4231],{"href":2322,"rel":4230,"target":40},[39],"public template repo","\non GitHub which is ready to go with no typing or other fiddling required.\nWith that, let's dive in!",[24,4234,4235],{},[1810,4236],{"alt":4237,"src":4238},"Ferrostar Architecture Diagram","\u002Fimages\u002Fcontent\u002Fferrostar-arch.png",[28,4240,4242],{"id":4241},"bindings-bridging-rust-and-platform-code","Bindings: Bridging Rust and Platform Code",[24,4244,4245,4246,4249],{},"If you're familiar with the concept of foreign function interfaces (FFIs),\nyou may remember ",[349,4247,4248],{},"extern"," declarations,\ncalling convention specifications,\nand having to write a lot of boilerplate.\nBut you know what is really good at generating boilerplate?\nComputers!\nEnter: binding generators.",[24,4251,4252,4253,4256,4257,4262],{},"Mozilla has developed a fantastic tool for binding generation:\n",[35,4254,2307],{"href":4141,"rel":4255,"target":40},[39],".\nIn their case, the motivation was to build pieces of Firefox\nwhich could be shared across platforms.\nUniFFI is designed to generate safe bindings that feel idiomatic\nto users of the target language.\nThe ",[35,4258,4261],{"href":4259,"rel":4260,"target":40},"https:\u002F\u002Fmozilla.github.io\u002Funiffi-rs\u002Finternals\u002Fdesign_principles.html",[39],"design principles","\nof UniFFI aligned well with our requirements for Ferrostar,\nand we think they tend to be a good fit for most similar mobile use cases.",[1205,4264,4266],{"id":4265},"cargo-workspace-setup","Cargo workspace setup",[24,4268,4269],{},"Let's dive in with discussing the cargo workspace setup for Ferrostar.\nThis should be a helpful guide for anyone wanting to create their own\ncross-platform library.",[24,4271,4272,4273,2686,4276,4278,4279,4282,4283,4285],{},"We chose to structure the Rust portion of our library as a workspace\nwith two member projects: ",[349,4274,4275],{},"uniffi-bindgen",[349,4277,2365],{},".\nAt the time of this writing,\nthe ability to run the binary from the ",[349,4280,4281],{},"uniffi"," crate\nis only available in nightly,\nso we opted for a second ",[349,4284,4275],{}," crate in our workspace\nfor the CLI binary.\nHere's what it looks like on disk:",[636,4287,4292],{"className":4288,"code":4290,"language":4291},[4289],"language-text","├── Cargo.lock\n├── Cargo.toml\n├── ferrostar\n│   ├── Cargo.toml\n│   └── src\n│       └── lib.rs\n└── uniffi-bindgen\n    ├── Cargo.toml\n    └── src\n        └── main.rs\n","text",[349,4293,4290],{"__ignoreMap":168},[24,4295,4296,4297,4300],{},"Scaffolding in place, we need to add UniFFI to our workspace's ",[349,4298,4299],{},"Cargo.toml",".\nThis way we can keep the binding generator and library versions in sync.\nAt the time this article was originally published,\nproc macro features were still under active development.\nSince then, they have stabilized somewhat,\nand it might make sense to start using the crates.io releases.\nIf you want the newest features and fixes though,\nit's best to use git dependencies.\nTracking the latest commits can cause pain,\nbut it is pretty rewarding if you want access to the latest improvements,\nwhich do come quite fast.",[636,4302,4306],{"className":4303,"code":4304,"language":4305,"meta":168,"style":168},"language-toml shiki shiki-themes github-light","[workspace]\n\nmembers = [\n    \"uniffi-bindgen\",\n    \"ferrostar\",\n]\nresolver = \"2\"\n\n[workspace.dependencies]\nuniffi = \"0.26.1\"\n","toml",[349,4307,4308,4319,4323,4328,4335,4342,4346,4354,4358,4371],{"__ignoreMap":168},[644,4309,4310,4313,4317],{"class":646,"line":647},[644,4311,4312],{"class":650},"[",[644,4314,4316],{"class":4315},"s7eDp","workspace",[644,4318,3743],{"class":650},[644,4320,4321],{"class":646,"line":172},[644,4322,1872],{"emptyLinePlaceholder":187},[644,4324,4325],{"class":646,"line":669},[644,4326,4327],{"class":650},"members = [\n",[644,4329,4330,4333],{"class":646,"line":169},[644,4331,4332],{"class":663},"    \"uniffi-bindgen\"",[644,4334,437],{"class":650},[644,4336,4337,4340],{"class":646,"line":692},[644,4338,4339],{"class":663},"    \"ferrostar\"",[644,4341,437],{"class":650},[644,4343,4344],{"class":646,"line":755},[644,4345,3743],{"class":650},[644,4347,4348,4351],{"class":646,"line":768},[644,4349,4350],{"class":650},"resolver = ",[644,4352,4353],{"class":663},"\"2\"\n",[644,4355,4356],{"class":646,"line":779},[644,4357,1872],{"emptyLinePlaceholder":187},[644,4359,4360,4362,4364,4366,4369],{"class":646,"line":1921},[644,4361,4312],{"class":650},[644,4363,4316],{"class":4315},[644,4365,458],{"class":650},[644,4367,4368],{"class":4315},"dependencies",[644,4370,3743],{"class":650},[644,4372,4373,4376],{"class":646,"line":1932},[644,4374,4375],{"class":650},"uniffi = ",[644,4377,4378],{"class":663},"\"0.26.1\"\n",[24,4380,4381,4382,2686,4384,4386,4387,4389,4390,4393],{},"Then, we can add it to the ",[349,4383,4275],{},[349,4385,2365],{}," crates respectively.\nIn the ",[349,4388,4275],{}," crate, we need the ",[349,4391,4392],{},"cli"," feature.",[636,4395,4397],{"className":4303,"code":4396,"language":4305,"meta":168,"style":168},"[dependencies]\nuniffi = { workspace = true, features = [\"cli\"] }\n",[349,4398,4399,4407],{"__ignoreMap":168},[644,4400,4401,4403,4405],{"class":646,"line":647},[644,4402,4312],{"class":650},[644,4404,4368],{"class":4315},[644,4406,3743],{"class":650},[644,4408,4409,4412,4414,4417,4420],{"class":646,"line":172},[644,4410,4411],{"class":650},"uniffi = { workspace = ",[644,4413,218],{"class":656},[644,4415,4416],{"class":650},", features = [",[644,4418,4419],{"class":663},"\"cli\"",[644,4421,4422],{"class":650},"] }\n",[24,4424,4425,4426,4429,4430,4433],{},"The ",[349,4427,4428],{},"main"," function in ",[349,4431,4432],{},"uniffi-bindgen\u002Fsrc\u002Fmain.rs"," is a single line.\nHere's the entire file:",[636,4435,4439],{"className":4436,"code":4437,"language":4438,"meta":168,"style":168},"language-rust shiki shiki-themes github-light","fn main() {\n    uniffi::uniffi_bindgen_main()\n}\n","rust",[349,4440,4441,4452,4466],{"__ignoreMap":168},[644,4442,4443,4446,4449],{"class":646,"line":647},[644,4444,4445],{"class":1846},"fn",[644,4447,4448],{"class":4315}," main",[644,4450,4451],{"class":650},"() {\n",[644,4453,4454,4457,4460,4463],{"class":646,"line":172},[644,4455,4456],{"class":4315},"    uniffi",[644,4458,4459],{"class":1846},"::",[644,4461,4462],{"class":4315},"uniffi_bindgen_main",[644,4464,4465],{"class":650},"()\n",[644,4467,4468],{"class":646,"line":669},[644,4469,695],{"class":650},[24,4471,4472,4473,4475,4476,4478,4479,4482,4483,458],{},"In the ",[349,4474,2365],{}," crate, we also need ",[349,4477,4281],{}," as a normal dependency\n",[611,4480,4481],{},"and"," build dependency.\nWe also need to configure the library target with a few different\n",[35,4484,4487,4490],{"href":4485,"rel":4486,"target":40},"https:\u002F\u002Fdoc.rust-lang.org\u002Freference\u002Flinkage.html",[39],[349,4488,4489],{},"crate_type","s",[56,4492,4493,4499,4509],{},[59,4494,4495,4498],{},[349,4496,4497],{},"cdylib"," - A dynamic system library. Used on most platforms.",[59,4500,4501,4504,4505,4508],{},[349,4502,4503],{},"staticlib"," - A system library with ",[611,4506,4507],{},"all"," upstream dependencies included.\nRequired to target iOS.",[59,4510,4511,4514,4515,4518],{},[349,4512,4513],{},"lib"," - A Rust library.\nThis isn't mentioned in the UniFFI documentation as of this writing,\nbut if you want to add integration tests (runnable via ",[349,4516,4517],{},"cargo test",")\nand you don't include a Rust library target,\nyou'll get strange errors.",[636,4520,4522],{"className":4303,"code":4521,"language":4305,"meta":168,"style":168},"[dependencies]\nuniffi.workspace = true\n\n[build-dependencies]\nuniffi = { workspace = true, features = [\"build\"] }\n\n[lib]\ncrate-type = [\"cdylib\", \"staticlib\", \"lib\"]\n",[349,4523,4524,4532,4540,4544,4553,4566,4570,4578],{"__ignoreMap":168},[644,4525,4526,4528,4530],{"class":646,"line":647},[644,4527,4312],{"class":650},[644,4529,4368],{"class":4315},[644,4531,3743],{"class":650},[644,4533,4534,4537],{"class":646,"line":172},[644,4535,4536],{"class":650},"uniffi.workspace = ",[644,4538,4539],{"class":656},"true\n",[644,4541,4542],{"class":646,"line":669},[644,4543,1872],{"emptyLinePlaceholder":187},[644,4545,4546,4548,4551],{"class":646,"line":169},[644,4547,4312],{"class":650},[644,4549,4550],{"class":4315},"build-dependencies",[644,4552,3743],{"class":650},[644,4554,4555,4557,4559,4561,4564],{"class":646,"line":692},[644,4556,4411],{"class":650},[644,4558,218],{"class":656},[644,4560,4416],{"class":650},[644,4562,4563],{"class":663},"\"build\"",[644,4565,4422],{"class":650},[644,4567,4568],{"class":646,"line":755},[644,4569,1872],{"emptyLinePlaceholder":187},[644,4571,4572,4574,4576],{"class":646,"line":768},[644,4573,4312],{"class":650},[644,4575,4513],{"class":4315},[644,4577,3743],{"class":650},[644,4579,4580,4583,4586,4588,4591,4593,4596],{"class":646,"line":779},[644,4581,4582],{"class":650},"crate-type = [",[644,4584,4585],{"class":663},"\"cdylib\"",[644,4587,352],{"class":650},[644,4589,4590],{"class":663},"\"staticlib\"",[644,4592,352],{"class":650},[644,4594,4595],{"class":663},"\"lib\"",[644,4597,3743],{"class":650},[1205,4599,4601],{"id":4600},"defining-what-to-export","Defining what to export",[24,4603,4604],{},"Internally, UniFFI uses an IDL (Interface Definition Language) to describe\nthe public interface of your crate to foreign code (ex: Swift and Kotlin).\nThis is similar to the process of writing a header file in C\nin that it is a set of definitions,\nbut the definition file is used to generate the foreign language bindings.",[24,4606,4607,4608,4610],{},"This used to require writing a bunch of boilerplate by hand.\nFortunately, UniFFI (starting from v0.25.0) automates this using procedural macros.\nFor our use case,\nwe were able to replace ",[611,4609,4507],{}," handwritten UDL with macros,\nand expect this will be the best path for most library authors going forward.",[4612,4613,4615],"h4",{"id":4614},"functions","Functions",[24,4617,4618,4619,4622],{},"Let's get started by exporting a function from Rust\nwhich generates a parser for routing data coming from our APIs.\nA single macro, ",[349,4620,4621],{},"uniffi:export"," is all we need to export a top-level function.",[636,4624,4626],{"className":4436,"code":4625,"language":4438,"meta":168,"style":168},"#[uniffi::export]\nfn create_osrm_response_parser(polyline_precision: u32) -> Arc\u003Cdyn RouteResponseParser> {\n    Arc::new(OsrmResponseParser::new(polyline_precision))\n}\n",[349,4627,4628,4638,4675,4697],{"__ignoreMap":168},[644,4629,4630,4633,4635],{"class":646,"line":647},[644,4631,4632],{"class":650},"#[uniffi",[644,4634,4459],{"class":1846},[644,4636,4637],{"class":650},"export]\n",[644,4639,4640,4642,4645,4648,4651,4654,4657,4660,4663,4666,4669,4672],{"class":646,"line":172},[644,4641,4445],{"class":1846},[644,4643,4644],{"class":4315}," create_osrm_response_parser",[644,4646,4647],{"class":650},"(polyline_precision",[644,4649,4650],{"class":1846},":",[644,4652,4653],{"class":4315}," u32",[644,4655,4656],{"class":650},") ",[644,4658,4659],{"class":1846},"->",[644,4661,4662],{"class":4315}," Arc",[644,4664,4665],{"class":650},"\u003C",[644,4667,4668],{"class":1846},"dyn",[644,4670,4671],{"class":4315}," RouteResponseParser",[644,4673,4674],{"class":650},"> {\n",[644,4676,4677,4680,4682,4685,4687,4690,4692,4694],{"class":646,"line":669},[644,4678,4679],{"class":4315},"    Arc",[644,4681,4459],{"class":1846},[644,4683,4684],{"class":4315},"new",[644,4686,2121],{"class":650},[644,4688,4689],{"class":4315},"OsrmResponseParser",[644,4691,4459],{"class":1846},[644,4693,4684],{"class":4315},[644,4695,4696],{"class":650},"(polyline_precision))\n",[644,4698,4699],{"class":646,"line":169},[644,4700,695],{"class":650},[24,4702,4703,4704,356,4707,4710,4711,352,4714,2686,4717,4720,4721,4724,4725,4728],{},"UniFFI macros generate the definitions for us automatically\nbased on the function's type signature.\nMany built-in types like numbers, ",[349,4705,4706],{},"String",[349,4708,4709],{},"bool","\n\"just work\" as you expect.\nCollections like ",[349,4712,4713],{},"Vec\u003CT>",[349,4715,4716],{},"Option\u003CT>",[349,4718,4719],{},"HashMap\u003CK, V>"," are also implemented\nfor all types that UniFFI knows how to represent over the FFI.\nThey even have special cases for types like ",[349,4722,4723],{},"Vec\u003Cu8>","\nwhich idiomatically map to a language-specific byte sequence type\n(ex: ",[349,4726,4727],{},"Data"," in Swift)!",[24,4730,4731],{},"If anything you export references a type\nthat UniFFI doesn't know how to convert,\nyou will get a compilation error.\nSo, how do we tell UniFFI about new types?",[4612,4733,4735],{"id":4734},"data-models","Data models",[24,4737,4738,4739,4742],{},"Let's look at two data models: user locations and route requests.\nWe'll export these using derive macros.\nIf you've used the ",[349,4740,4741],{},"serde"," crate, this should feel familiar.",[24,4744,4745,4746,4749,4750,4753,4754,4757],{},"User location is just a struct with some properties like coordinates\nand course over ground.\nThe ",[349,4747,4748],{},"uniffi::Record"," macro exposes our Rust types idiomatically.\nThey will show up as ",[349,4751,4752],{},"struct","s in Swift, and ",[349,4755,4756],{},"data class","es in Kotlin.",[636,4759,4761],{"className":4436,"code":4760,"language":4438,"meta":168,"style":168},"#[derive(uniffi::Record)]\npub struct UserLocation {\n    pub coordinates: GeographicCoordinates,\n    pub horizontal_accuracy: f64,\n    pub course_over_ground: Option\u003CCourseOverGround>,\n    pub timestamp: SystemTime,\n}\n",[349,4762,4763,4776,4789,4804,4818,4838,4852],{"__ignoreMap":168},[644,4764,4765,4768,4770,4773],{"class":646,"line":647},[644,4766,4767],{"class":650},"#[derive(uniffi",[644,4769,4459],{"class":1846},[644,4771,4772],{"class":4315},"Record",[644,4774,4775],{"class":650},")]\n",[644,4777,4778,4781,4784,4787],{"class":646,"line":172},[644,4779,4780],{"class":1846},"pub",[644,4782,4783],{"class":1846}," struct",[644,4785,4786],{"class":4315}," UserLocation",[644,4788,1947],{"class":650},[644,4790,4791,4794,4797,4799,4802],{"class":646,"line":669},[644,4792,4793],{"class":1846},"    pub",[644,4795,4796],{"class":650}," coordinates",[644,4798,4650],{"class":1846},[644,4800,4801],{"class":4315}," GeographicCoordinates",[644,4803,437],{"class":650},[644,4805,4806,4808,4811,4813,4816],{"class":646,"line":169},[644,4807,4793],{"class":1846},[644,4809,4810],{"class":650}," horizontal_accuracy",[644,4812,4650],{"class":1846},[644,4814,4815],{"class":4315}," f64",[644,4817,437],{"class":650},[644,4819,4820,4822,4825,4827,4830,4832,4835],{"class":646,"line":692},[644,4821,4793],{"class":1846},[644,4823,4824],{"class":650}," course_over_ground",[644,4826,4650],{"class":1846},[644,4828,4829],{"class":4315}," Option",[644,4831,4665],{"class":650},[644,4833,4834],{"class":4315},"CourseOverGround",[644,4836,4837],{"class":650},">,\n",[644,4839,4840,4842,4845,4847,4850],{"class":646,"line":755},[644,4841,4793],{"class":1846},[644,4843,4844],{"class":650}," timestamp",[644,4846,4650],{"class":1846},[644,4848,4849],{"class":4315}," SystemTime",[644,4851,437],{"class":650},[644,4853,4854],{"class":646,"line":768},[644,4855,695],{"class":650},[24,4857,4858],{},"Route requests are a little different.\nThey don't really map to a record type.\nSince we want to build an extensible framework,\nwe need to account for multiple ways of getting a route.\nFor example, making an HTTP request, or computing a route on-device.",[24,4860,4861,4862,4865],{},"This maps well to an enumeration.\nThe ",[349,4863,4864],{},"uniffi::Enum"," derive macro exports these like you would expect.",[636,4867,4869],{"className":4436,"code":4868,"language":4438,"meta":168,"style":168},"#[derive(uniffi::Enum)]\npub enum RouteRequest {\n    HttpPost {\n        url: String,\n        headers: HashMap\u003CString, String>,\n        body: Vec\u003Cu8>,\n    },\n    \u002F\u002F ...\n}\n",[349,4870,4871,4882,4894,4901,4912,4932,4949,4953,4958],{"__ignoreMap":168},[644,4872,4873,4875,4877,4880],{"class":646,"line":647},[644,4874,4767],{"class":650},[644,4876,4459],{"class":1846},[644,4878,4879],{"class":4315},"Enum",[644,4881,4775],{"class":650},[644,4883,4884,4886,4889,4892],{"class":646,"line":172},[644,4885,4780],{"class":1846},[644,4887,4888],{"class":1846}," enum",[644,4890,4891],{"class":4315}," RouteRequest",[644,4893,1947],{"class":650},[644,4895,4896,4899],{"class":646,"line":669},[644,4897,4898],{"class":4315},"    HttpPost",[644,4900,1947],{"class":650},[644,4902,4903,4905,4907,4910],{"class":646,"line":169},[644,4904,2010],{"class":650},[644,4906,4650],{"class":1846},[644,4908,4909],{"class":4315}," String",[644,4911,437],{"class":650},[644,4913,4914,4917,4919,4922,4924,4926,4928,4930],{"class":646,"line":692},[644,4915,4916],{"class":650},"        headers",[644,4918,4650],{"class":1846},[644,4920,4921],{"class":4315}," HashMap",[644,4923,4665],{"class":650},[644,4925,4706],{"class":4315},[644,4927,352],{"class":650},[644,4929,4706],{"class":4315},[644,4931,4837],{"class":650},[644,4933,4934,4937,4939,4942,4944,4947],{"class":646,"line":755},[644,4935,4936],{"class":650},"        body",[644,4938,4650],{"class":1846},[644,4940,4941],{"class":4315}," Vec",[644,4943,4665],{"class":650},[644,4945,4946],{"class":4315},"u8",[644,4948,4837],{"class":650},[644,4950,4951],{"class":646,"line":768},[644,4952,3686],{"class":650},[644,4954,4955],{"class":646,"line":779},[644,4956,4957],{"class":1866},"    \u002F\u002F ...\n",[644,4959,4960],{"class":646,"line":1921},[644,4961,695],{"class":650},[4612,4963,4965],{"id":4964},"objects","Objects",[24,4967,4968],{},"You can also export more complex objects\nwith local state, methods, and constructors!",[24,4970,4971],{},"One example of this in Ferrostar is our route adapter.\nIt stores a request generator and response parser\nand exposes a generic interface\nso the caller doesn't need to know about the details.",[636,4973,4975],{"className":4436,"code":4974,"language":4438,"meta":168,"style":168},"#[derive(uniffi::Object)]\npub struct RouteAdapter {\n    request_generator: Arc\u003Cdyn RouteRequestGenerator>,\n    response_parser: Arc\u003Cdyn RouteResponseParser>,\n}\n\n#[uniffi::export]\nimpl RouteAdapter {\n    #[uniffi::constructor]\n    pub fn new(\n        request_generator: Arc\u003Cdyn RouteRequestGenerator>,\n        response_parser: Arc\u003Cdyn RouteResponseParser>,\n    ) -> Self {\n        Self {\n            request_generator,\n            response_parser,\n        }\n    }\n\n    #[uniffi::constructor]\n    pub fn new_valhalla_http(endpoint_url: String, profile: String) -> Arc\u003CSelf> {\n        let request_generator = create_valhalla_request_generator(endpoint_url, profile);\n        let response_parser = create_osrm_response_parser(6);\n        Self::new(request_generator, response_parser)\n    }\n\n    pub fn generate_request(\n        &self,\n        user_location: UserLocation,\n        waypoints: Vec\u003CGeographicCoordinates>,\n    ) -> Result\u003CRouteRequest, RoutingRequestGenerationError> {\n        self.request_generator\n            .generate_request(user_location, waypoints)\n    }\n\n    pub fn parse_response(\n        &self,\n        response: Vec\u003Cu8>,\n    ) -> Result\u003CVec\u003CRoute>, RoutingResponseParseError> {\n        self.response_parser.parse_response(response)\n    }\n}\n",[349,4976,4977,4988,4999,5017,5034,5038,5042,5050,5059,5069,5081,5098,5115,5127,5134,5139,5144,5149,5153,5157,5165,5201,5217,5236,5247,5251,5255,5266,5276,5287,5303,5325,5336,5348,5353,5358,5370,5379,5395,5422,5440,5445],{"__ignoreMap":168},[644,4978,4979,4981,4983,4986],{"class":646,"line":647},[644,4980,4767],{"class":650},[644,4982,4459],{"class":1846},[644,4984,4985],{"class":4315},"Object",[644,4987,4775],{"class":650},[644,4989,4990,4992,4994,4997],{"class":646,"line":172},[644,4991,4780],{"class":1846},[644,4993,4783],{"class":1846},[644,4995,4996],{"class":4315}," RouteAdapter",[644,4998,1947],{"class":650},[644,5000,5001,5004,5006,5008,5010,5012,5015],{"class":646,"line":669},[644,5002,5003],{"class":650},"    request_generator",[644,5005,4650],{"class":1846},[644,5007,4662],{"class":4315},[644,5009,4665],{"class":650},[644,5011,4668],{"class":1846},[644,5013,5014],{"class":4315}," RouteRequestGenerator",[644,5016,4837],{"class":650},[644,5018,5019,5022,5024,5026,5028,5030,5032],{"class":646,"line":169},[644,5020,5021],{"class":650},"    response_parser",[644,5023,4650],{"class":1846},[644,5025,4662],{"class":4315},[644,5027,4665],{"class":650},[644,5029,4668],{"class":1846},[644,5031,4671],{"class":4315},[644,5033,4837],{"class":650},[644,5035,5036],{"class":646,"line":692},[644,5037,695],{"class":650},[644,5039,5040],{"class":646,"line":755},[644,5041,1872],{"emptyLinePlaceholder":187},[644,5043,5044,5046,5048],{"class":646,"line":768},[644,5045,4632],{"class":650},[644,5047,4459],{"class":1846},[644,5049,4637],{"class":650},[644,5051,5052,5055,5057],{"class":646,"line":779},[644,5053,5054],{"class":1846},"impl",[644,5056,4996],{"class":4315},[644,5058,1947],{"class":650},[644,5060,5061,5064,5066],{"class":646,"line":1921},[644,5062,5063],{"class":650},"    #[uniffi",[644,5065,4459],{"class":1846},[644,5067,5068],{"class":650},"constructor]\n",[644,5070,5071,5073,5076,5079],{"class":646,"line":1932},[644,5072,4793],{"class":1846},[644,5074,5075],{"class":1846}," fn",[644,5077,5078],{"class":4315}," new",[644,5080,1896],{"class":650},[644,5082,5083,5086,5088,5090,5092,5094,5096],{"class":646,"line":1938},[644,5084,5085],{"class":650},"        request_generator",[644,5087,4650],{"class":1846},[644,5089,4662],{"class":4315},[644,5091,4665],{"class":650},[644,5093,4668],{"class":1846},[644,5095,5014],{"class":4315},[644,5097,4837],{"class":650},[644,5099,5100,5103,5105,5107,5109,5111,5113],{"class":646,"line":1950},[644,5101,5102],{"class":650},"        response_parser",[644,5104,4650],{"class":1846},[644,5106,4662],{"class":4315},[644,5108,4665],{"class":650},[644,5110,4668],{"class":1846},[644,5112,4671],{"class":4315},[644,5114,4837],{"class":650},[644,5116,5117,5120,5122,5125],{"class":646,"line":1956},[644,5118,5119],{"class":650},"    ) ",[644,5121,4659],{"class":1846},[644,5123,5124],{"class":656}," Self",[644,5126,1947],{"class":650},[644,5128,5129,5132],{"class":646,"line":1970},[644,5130,5131],{"class":656},"        Self",[644,5133,1947],{"class":650},[644,5135,5136],{"class":646,"line":1983},[644,5137,5138],{"class":650},"            request_generator,\n",[644,5140,5141],{"class":646,"line":1996},[644,5142,5143],{"class":650},"            response_parser,\n",[644,5145,5146],{"class":646,"line":2007},[644,5147,5148],{"class":650},"        }\n",[644,5150,5151],{"class":646,"line":2016},[644,5152,3643],{"class":650},[644,5154,5155],{"class":646,"line":2030},[644,5156,1872],{"emptyLinePlaceholder":187},[644,5158,5159,5161,5163],{"class":646,"line":2039},[644,5160,5063],{"class":650},[644,5162,4459],{"class":1846},[644,5164,5068],{"class":650},[644,5166,5167,5169,5171,5174,5177,5179,5181,5184,5186,5188,5190,5192,5194,5196,5199],{"class":646,"line":2044},[644,5168,4793],{"class":1846},[644,5170,5075],{"class":1846},[644,5172,5173],{"class":4315}," new_valhalla_http",[644,5175,5176],{"class":650},"(endpoint_url",[644,5178,4650],{"class":1846},[644,5180,4909],{"class":4315},[644,5182,5183],{"class":650},", profile",[644,5185,4650],{"class":1846},[644,5187,4909],{"class":4315},[644,5189,4656],{"class":650},[644,5191,4659],{"class":1846},[644,5193,4662],{"class":4315},[644,5195,4665],{"class":650},[644,5197,5198],{"class":656},"Self",[644,5200,4674],{"class":650},[644,5202,5203,5206,5209,5211,5214],{"class":646,"line":3746},[644,5204,5205],{"class":1846},"        let",[644,5207,5208],{"class":650}," request_generator ",[644,5210,1860],{"class":1846},[644,5212,5213],{"class":4315}," create_valhalla_request_generator",[644,5215,5216],{"class":650},"(endpoint_url, profile);\n",[644,5218,5219,5221,5224,5226,5228,5230,5233],{"class":646,"line":3751},[644,5220,5205],{"class":1846},[644,5222,5223],{"class":650}," response_parser ",[644,5225,1860],{"class":1846},[644,5227,4644],{"class":4315},[644,5229,2121],{"class":650},[644,5231,5232],{"class":656},"6",[644,5234,5235],{"class":650},");\n",[644,5237,5238,5240,5242,5244],{"class":646,"line":3756},[644,5239,5131],{"class":656},[644,5241,4459],{"class":1846},[644,5243,4684],{"class":4315},[644,5245,5246],{"class":650},"(request_generator, response_parser)\n",[644,5248,5249],{"class":646,"line":3768},[644,5250,3643],{"class":650},[644,5252,5253],{"class":646,"line":3780},[644,5254,1872],{"emptyLinePlaceholder":187},[644,5256,5257,5259,5261,5264],{"class":646,"line":3792},[644,5258,4793],{"class":1846},[644,5260,5075],{"class":1846},[644,5262,5263],{"class":4315}," generate_request",[644,5265,1896],{"class":650},[644,5267,5268,5271,5274],{"class":646,"line":3803},[644,5269,5270],{"class":1846},"        &",[644,5272,5273],{"class":656},"self",[644,5275,437],{"class":650},[644,5277,5278,5281,5283,5285],{"class":646,"line":3808},[644,5279,5280],{"class":650},"        user_location",[644,5282,4650],{"class":1846},[644,5284,4786],{"class":4315},[644,5286,437],{"class":650},[644,5288,5289,5292,5294,5296,5298,5301],{"class":646,"line":3814},[644,5290,5291],{"class":650},"        waypoints",[644,5293,4650],{"class":1846},[644,5295,4941],{"class":4315},[644,5297,4665],{"class":650},[644,5299,5300],{"class":4315},"GeographicCoordinates",[644,5302,4837],{"class":650},[644,5304,5306,5308,5310,5313,5315,5318,5320,5323],{"class":646,"line":5305},31,[644,5307,5119],{"class":650},[644,5309,4659],{"class":1846},[644,5311,5312],{"class":4315}," Result",[644,5314,4665],{"class":650},[644,5316,5317],{"class":4315},"RouteRequest",[644,5319,352],{"class":650},[644,5321,5322],{"class":4315},"RoutingRequestGenerationError",[644,5324,4674],{"class":650},[644,5326,5328,5331,5333],{"class":646,"line":5327},32,[644,5329,5330],{"class":656},"        self",[644,5332,458],{"class":1846},[644,5334,5335],{"class":650},"request_generator\n",[644,5337,5339,5342,5345],{"class":646,"line":5338},33,[644,5340,5341],{"class":1846},"            .",[644,5343,5344],{"class":4315},"generate_request",[644,5346,5347],{"class":650},"(user_location, waypoints)\n",[644,5349,5351],{"class":646,"line":5350},34,[644,5352,3643],{"class":650},[644,5354,5356],{"class":646,"line":5355},35,[644,5357,1872],{"emptyLinePlaceholder":187},[644,5359,5361,5363,5365,5368],{"class":646,"line":5360},36,[644,5362,4793],{"class":1846},[644,5364,5075],{"class":1846},[644,5366,5367],{"class":4315}," parse_response",[644,5369,1896],{"class":650},[644,5371,5373,5375,5377],{"class":646,"line":5372},37,[644,5374,5270],{"class":1846},[644,5376,5273],{"class":656},[644,5378,437],{"class":650},[644,5380,5382,5385,5387,5389,5391,5393],{"class":646,"line":5381},38,[644,5383,5384],{"class":650},"        response",[644,5386,4650],{"class":1846},[644,5388,4941],{"class":4315},[644,5390,4665],{"class":650},[644,5392,4946],{"class":4315},[644,5394,4837],{"class":650},[644,5396,5398,5400,5402,5404,5406,5409,5411,5414,5417,5420],{"class":646,"line":5397},39,[644,5399,5119],{"class":650},[644,5401,4659],{"class":1846},[644,5403,5312],{"class":4315},[644,5405,4665],{"class":650},[644,5407,5408],{"class":4315},"Vec",[644,5410,4665],{"class":650},[644,5412,5413],{"class":4315},"Route",[644,5415,5416],{"class":650},">, ",[644,5418,5419],{"class":4315},"RoutingResponseParseError",[644,5421,4674],{"class":650},[644,5423,5425,5427,5429,5432,5434,5437],{"class":646,"line":5424},40,[644,5426,5330],{"class":656},[644,5428,458],{"class":1846},[644,5430,5431],{"class":650},"response_parser",[644,5433,458],{"class":1846},[644,5435,5436],{"class":4315},"parse_response",[644,5438,5439],{"class":650},"(response)\n",[644,5441,5443],{"class":646,"line":5442},41,[644,5444,3643],{"class":650},[644,5446,5448],{"class":646,"line":5447},42,[644,5449,695],{"class":650},[24,5451,5452,5453,5456,5457,5459],{},"This example is a bit more complicated than the others we've looked at so far.\nFirst, we use the ",[349,5454,5455],{},"uniffi::Object"," derive macro on the struct.\nIn contrast to ",[349,5458,4748],{},",\nthis signals that the type will be passed by reference and may have methods.\nThis will be exposed in Swift or Kotlin as a class.",[24,5461,5462,5463,5466,5467,5470,5471,5473,5474,5477],{},"You must annotate your constructors with the ",[349,5464,5465],{},"uniffi::constructor"," macro.\nAt the time of this writing, constructors must return an ",[349,5468,5469],{},"Arc\u003CSelf>",".\nThe ",[349,5472,4684],{}," constructor is special, and is exposed most naturally,\nbut other named constructors are also supported if you mark them as such.\nThey are not currently as idiomatic as the default constructor,\nbut I expect things like exposing a ",[349,5475,5476],{},"convenience init"," to Swift\nwill be possible in the future.",[24,5479,5480,5481,5483,5484,5487,5488,5491,5492,5495,5496,5499,5500,5503],{},"Finally, types exported with ",[349,5482,5455],{}," tell the binding generator\nto emit a ",[349,5485,5486],{},"protocol"," (Swift) or ",[349,5489,5490],{},"interface"," (Kotlin) definition.\n",[62,5493,5494],{},"Pro tip:"," This makes it easier for you to write mock implementations\nfor unit testing!\nOur rule of thumb is to ",[611,5497,5498],{},"pass"," the protocol\u002Finterface to your native methods,\nand define your instance variables with protocol\u002Finterface types.\nWhen the time comes to construct one,\nyour business logic will dictate which ",[611,5501,5502],{},"concrete"," implementation to construct.\nThis makes your code significantly more extensible,\nand allows you to either use implementations from the Rust core\nor define your own in Swift\u002FKotlin.",[4612,5505,5507],{"id":5506},"errors","Errors",[24,5509,5510],{},"Result types in Rust signal errors,\nand UniFFI can expose these idiomatically in the generated bindings.\nWe use this pattern in the above example to signal response parsing errors.",[636,5512,5514],{"className":4436,"code":5513,"language":4438,"meta":168,"style":168},"#[derive(Debug, thiserror::Error, uniffi::Error)]\npub enum RoutingResponseParseError {\n    #[error(\"Failed to parse route response: {error}.\")]\n    ParseError { error: String },\n    \u002F\u002F ...\n    #[error(\"An unknown error parsing a response was raised in foreign code.\")]\n    UnknownError,\n}\n",[349,5515,5516,5541,5552,5562,5577,5581,5590,5597],{"__ignoreMap":168},[644,5517,5518,5521,5524,5527,5529,5532,5535,5537,5539],{"class":646,"line":647},[644,5519,5520],{"class":650},"#[derive(",[644,5522,5523],{"class":4315},"Debug",[644,5525,5526],{"class":650},", thiserror",[644,5528,4459],{"class":1846},[644,5530,5531],{"class":4315},"Error",[644,5533,5534],{"class":650},", uniffi",[644,5536,4459],{"class":1846},[644,5538,5531],{"class":4315},[644,5540,4775],{"class":650},[644,5542,5543,5545,5547,5550],{"class":646,"line":172},[644,5544,4780],{"class":1846},[644,5546,4888],{"class":1846},[644,5548,5549],{"class":4315}," RoutingResponseParseError",[644,5551,1947],{"class":650},[644,5553,5554,5557,5560],{"class":646,"line":669},[644,5555,5556],{"class":650},"    #[error(",[644,5558,5559],{"class":663},"\"Failed to parse route response: {error}.\"",[644,5561,4775],{"class":650},[644,5563,5564,5567,5570,5572,5574],{"class":646,"line":169},[644,5565,5566],{"class":4315},"    ParseError",[644,5568,5569],{"class":650}," { error",[644,5571,4650],{"class":1846},[644,5573,4909],{"class":4315},[644,5575,5576],{"class":650}," },\n",[644,5578,5579],{"class":646,"line":692},[644,5580,4957],{"class":1866},[644,5582,5583,5585,5588],{"class":646,"line":755},[644,5584,5556],{"class":650},[644,5586,5587],{"class":663},"\"An unknown error parsing a response was raised in foreign code.\"",[644,5589,4775],{"class":650},[644,5591,5592,5595],{"class":646,"line":768},[644,5593,5594],{"class":4315},"    UnknownError",[644,5596,437],{"class":650},[644,5598,5599],{"class":646,"line":779},[644,5600,695],{"class":650},[24,5602,4425,5603,5606,5607,5610,5611,5614,5615,5617,5618,5621],{},[349,5604,5605],{},"uniffi::Error"," derive macro will work with any type\nconforming to ",[349,5608,5609],{},"std::Error",".\nWe make extensive use of ",[349,5612,5613],{},"thiserror"," for simplicity.\nIn Swift and Kotlin code,\nthis definition will be bridged into an enum conforming to ",[349,5616,5531],{},"\nand a sealed subclass of ",[349,5619,5620],{},"Exception"," respectively.",[24,5623,5624],{},"Besides exposing the error types themselves,\nUniFFI also makes the error handling idiomatic.\nLet's return to the response parsing function signature.",[636,5626,5628],{"className":4436,"code":5627,"language":4438,"meta":168,"style":168},"pub fn parse_response(\n    &self,\n    response: Vec\u003Cu8>,\n) -> Result\u003CVec\u003CRoute>, RoutingResponseParseError>\n",[349,5629,5630,5640,5649,5664],{"__ignoreMap":168},[644,5631,5632,5634,5636,5638],{"class":646,"line":647},[644,5633,4780],{"class":1846},[644,5635,5075],{"class":1846},[644,5637,5367],{"class":4315},[644,5639,1896],{"class":650},[644,5641,5642,5645,5647],{"class":646,"line":172},[644,5643,5644],{"class":1846},"    &",[644,5646,5273],{"class":656},[644,5648,437],{"class":650},[644,5650,5651,5654,5656,5658,5660,5662],{"class":646,"line":669},[644,5652,5653],{"class":650},"    response",[644,5655,4650],{"class":1846},[644,5657,4941],{"class":4315},[644,5659,4665],{"class":650},[644,5661,4946],{"class":4315},[644,5663,4837],{"class":650},[644,5665,5666,5668,5670,5672,5674,5676,5678,5680,5682,5684],{"class":646,"line":169},[644,5667,4656],{"class":650},[644,5669,4659],{"class":1846},[644,5671,5312],{"class":4315},[644,5673,4665],{"class":650},[644,5675,5408],{"class":4315},[644,5677,4665],{"class":650},[644,5679,5413],{"class":4315},[644,5681,5416],{"class":650},[644,5683,5419],{"class":4315},[644,5685,5686],{"class":650},">\n",[24,5688,5689,5690,5692],{},"Semantically speaking,\nthis function will either return an ordered list of routes,\nor it will generate an error of type ",[349,5691,5419],{},".\nAs such, this is how the generated Swift bindings will look:",[636,5694,5696],{"className":1837,"code":5695,"language":1839,"meta":168,"style":168},"public func parseResponse(response: Data) throws -> [Route]\n",[349,5697,5698],{"__ignoreMap":168},[644,5699,5700,5703,5706,5709,5711,5714,5717,5720,5723],{"class":646,"line":647},[644,5701,5702],{"class":1846},"public",[644,5704,5705],{"class":1846}," func",[644,5707,5708],{"class":4315}," parseResponse",[644,5710,2121],{"class":650},[644,5712,5713],{"class":4315},"response",[644,5715,5716],{"class":650},": Data) ",[644,5718,5719],{"class":1846},"throws",[644,5721,5722],{"class":1846}," ->",[644,5724,5725],{"class":650}," [Route]\n",[24,5727,5728,5729,5731],{},"Swift does not explicitly list error types, but uses the ",[349,5730,5719],{}," keyword.\nIf you inspect the generated code,\nyou can see that UniFFI does indeed handle error variants,\nmapping them to your error types.",[4612,5733,5735],{"id":5734},"traits","Traits",[24,5737,5738],{},"Carrying on the motivating use case of vendor-agnostic routing API integration,\nwe define traits in our crate for response parsing\nand similar things that we want to ensure remain generic.",[636,5740,5742],{"className":4436,"code":5741,"language":4438,"meta":168,"style":168},"#[uniffi::export(with_foreign)]\npub trait RouteResponseParser: Send + Sync {\n    \u002F\u002F\u002F Parses a raw response from the routing backend into a route.\n    fn parse_response(&self, response: Vec\u003Cu8>) -> Result\u003CVec\u003CRoute>, RoutingResponseParseError>;\n}\n",[349,5743,5744,5753,5775,5780,5827],{"__ignoreMap":168},[644,5745,5746,5748,5750],{"class":646,"line":647},[644,5747,4632],{"class":650},[644,5749,4459],{"class":1846},[644,5751,5752],{"class":650},"export(with_foreign)]\n",[644,5754,5755,5757,5760,5762,5764,5767,5770,5773],{"class":646,"line":172},[644,5756,4780],{"class":1846},[644,5758,5759],{"class":1846}," trait",[644,5761,4671],{"class":4315},[644,5763,4650],{"class":1846},[644,5765,5766],{"class":4315}," Send",[644,5768,5769],{"class":1846}," +",[644,5771,5772],{"class":4315}," Sync",[644,5774,1947],{"class":650},[644,5776,5777],{"class":646,"line":669},[644,5778,5779],{"class":1866},"    \u002F\u002F\u002F Parses a raw response from the routing backend into a route.\n",[644,5781,5782,5785,5787,5789,5792,5794,5797,5799,5801,5803,5805,5808,5810,5812,5814,5816,5818,5820,5822,5824],{"class":646,"line":169},[644,5783,5784],{"class":1846},"    fn",[644,5786,5367],{"class":4315},[644,5788,2121],{"class":650},[644,5790,5791],{"class":1846},"&",[644,5793,5273],{"class":656},[644,5795,5796],{"class":650},", response",[644,5798,4650],{"class":1846},[644,5800,4941],{"class":4315},[644,5802,4665],{"class":650},[644,5804,4946],{"class":4315},[644,5806,5807],{"class":650},">) ",[644,5809,4659],{"class":1846},[644,5811,5312],{"class":4315},[644,5813,4665],{"class":650},[644,5815,5408],{"class":4315},[644,5817,4665],{"class":650},[644,5819,5413],{"class":4315},[644,5821,5416],{"class":650},[644,5823,5419],{"class":4315},[644,5825,5826],{"class":650},">;\n",[644,5828,5829],{"class":646,"line":692},[644,5830,695],{"class":650},[24,5832,5833,5834,5837,5838,5841,5842,5845],{},"You can export traits with the ",[349,5835,5836],{},"uniffi::export"," macro,\nand will they show up as protocols\u002Finterfaces in your foreign code.\nEven better, if you use ",[349,5839,5840],{},"with_foreign",", you can supply foreign code to Rust!\nIt requires a bit of a dance Rust-side\n(you must use types of the form ",[349,5843,5844],{},"Arc\u003Cdyn Trait>"," at the time of this writing),\nbut that's a small price to pay for such flexibility.",[24,5847,5848,5849,5852,5853,5855,5856,5858],{},"Here's what it looks like in Swift.\nFirst, the Rust ",[349,5850,5851],{},"trait"," is translated into a Swift ",[349,5854,5486],{}," automatically\nby the UniFFI binding generator.\nThe method even has ",[349,5857,5719],{},", just like you'd write in a pure Swift project!",[636,5860,5862],{"className":1837,"code":5861,"language":1839,"meta":168,"style":168},"public protocol RouteResponseParser: AnyObject {\n    \u002F**\n     * Parses a raw response from the routing backend into a route.\n     *\n     * We use a sequence of octets as a common interchange format.\n     * as this works for all currently conceivable formats (JSON, PBF, etc.).\n     *\u002F\n    func parseResponse(response: Data) throws -> [Route]\n}\n",[349,5863,5864,5880,5885,5890,5895,5900,5905,5910,5929],{"__ignoreMap":168},[644,5865,5866,5868,5871,5873,5875,5878],{"class":646,"line":647},[644,5867,5702],{"class":1846},[644,5869,5870],{"class":1846}," protocol",[644,5872,4671],{"class":4315},[644,5874,660],{"class":650},[644,5876,5877],{"class":656},"AnyObject",[644,5879,1947],{"class":650},[644,5881,5882],{"class":646,"line":172},[644,5883,5884],{"class":1866},"    \u002F**\n",[644,5886,5887],{"class":646,"line":669},[644,5888,5889],{"class":1866},"     * Parses a raw response from the routing backend into a route.\n",[644,5891,5892],{"class":646,"line":169},[644,5893,5894],{"class":1866},"     *\n",[644,5896,5897],{"class":646,"line":692},[644,5898,5899],{"class":1866},"     * We use a sequence of octets as a common interchange format.\n",[644,5901,5902],{"class":646,"line":755},[644,5903,5904],{"class":1866},"     * as this works for all currently conceivable formats (JSON, PBF, etc.).\n",[644,5906,5907],{"class":646,"line":768},[644,5908,5909],{"class":1866},"     *\u002F\n",[644,5911,5912,5915,5917,5919,5921,5923,5925,5927],{"class":646,"line":779},[644,5913,5914],{"class":1846},"    func",[644,5916,5708],{"class":4315},[644,5918,2121],{"class":650},[644,5920,5713],{"class":4315},[644,5922,5716],{"class":650},[644,5924,5719],{"class":1846},[644,5926,5722],{"class":1846},[644,5928,5725],{"class":650},[644,5930,5931],{"class":646,"line":1921},[644,5932,695],{"class":650},[24,5934,5935,5936,5939,5940,5942],{},"Now we can implement it just like any other protocol.\nHere's an example of an implementation that we use in our testing.\nIt's a mock that is initialized with a fixed set of routes for\n\"end-to-end\" tests without hitting a network service.\nIn the real world, you might use ",[349,5937,5938],{},"Codable","\nto convert the raw data into a Swift model\nand then map it to Ferrostar ",[349,5941,5413],{},"s.",[636,5944,5946],{"className":1837,"code":5945,"language":1839,"meta":168,"style":168},"class MockRouteResponseParser: RouteResponseParser {\n    private let routes: [Route]\n\n    init(routes: [Route]) {\n        self.routes = routes\n    }\n\n    func parseResponse(response _: Data) throws -> [Route] {\n        routes\n    }\n}\n",[349,5947,5948,5963,5974,5978,5991,6003,6007,6011,6031,6036,6040],{"__ignoreMap":168},[644,5949,5950,5953,5956,5958,5961],{"class":646,"line":647},[644,5951,5952],{"class":1846},"class",[644,5954,5955],{"class":4315}," MockRouteResponseParser",[644,5957,660],{"class":650},[644,5959,5960],{"class":4315},"RouteResponseParser ",[644,5962,651],{"class":650},[644,5964,5965,5968,5971],{"class":646,"line":172},[644,5966,5967],{"class":1846},"    private",[644,5969,5970],{"class":1846}," let",[644,5972,5973],{"class":650}," routes: [Route]\n",[644,5975,5976],{"class":646,"line":669},[644,5977,1872],{"emptyLinePlaceholder":187},[644,5979,5980,5983,5985,5988],{"class":646,"line":169},[644,5981,5982],{"class":1846},"    init",[644,5984,2121],{"class":650},[644,5986,5987],{"class":4315},"routes",[644,5989,5990],{"class":650},": [Route]) {\n",[644,5992,5993,5995,5998,6000],{"class":646,"line":692},[644,5994,5330],{"class":656},[644,5996,5997],{"class":650},".routes ",[644,5999,1860],{"class":1846},[644,6001,6002],{"class":650}," routes\n",[644,6004,6005],{"class":646,"line":755},[644,6006,3643],{"class":650},[644,6008,6009],{"class":646,"line":768},[644,6010,1872],{"emptyLinePlaceholder":187},[644,6012,6013,6015,6017,6019,6021,6024,6026,6028],{"class":646,"line":779},[644,6014,5914],{"class":1846},[644,6016,5708],{"class":4315},[644,6018,2121],{"class":650},[644,6020,5713],{"class":4315},[644,6022,6023],{"class":650}," _: Data) ",[644,6025,5719],{"class":1846},[644,6027,5722],{"class":1846},[644,6029,6030],{"class":650}," [Route] {\n",[644,6032,6033],{"class":646,"line":1921},[644,6034,6035],{"class":650},"        routes\n",[644,6037,6038],{"class":646,"line":1932},[644,6039,3643],{"class":650},[644,6041,6042],{"class":646,"line":1938},[644,6043,695],{"class":650},[24,6045,6046,6047,2686,6050,6053],{},"By making things like ",[349,6048,6049],{},"RouteRequestGenerator",[349,6051,6052],{},"RouteResponseParser"," traits,\nwe make it possible for anyone to do the following:",[107,6055,6056,6059,6062],{},[59,6057,6058],{},"Connect to a custom routing server (for example, one they are self-hosting).",[59,6060,6061],{},"Parse routes in a different format.",[59,6063,6064],{},"Generate routes on-device (in another library, Swift, Kotlin, etc.).",[24,6066,6067],{},"We're really excited about how this will enable more innovation by developers,\nsince Ferrostar will be easily adaptable to custom routing backends,\nboth for research and commercial use.",[28,6069,6071],{"id":6070},"what-works-well","What works well?",[24,6073,6074,6075,6077],{},"The APIs UniFFI generates truly feel idiomatic!\nIt's hard to overstate how nice this is.\nIt also goes out of its way to generate protocols\u002Finterfaces,\nwhich make it easy to mock parts for unit testing in native code,\nand even has pleasant surprises\nlike ",[349,6076,4723],{}," mapping to idiomatic byte sequence types.",[24,6079,6080,6081,6084],{},"UniFFI encourages good hygiene all the way from Rust to your application code\nvia type safety.\nAny type that appears in your signature must be exported,\nso you get checks from end to end.\nAnd Rust functions that return a ",[349,6082,6083],{},"Result"," type\nare translated into idiomatic errors and exceptions.",[24,6086,6087,6088,6093],{},"You can even bridge custom types!\nWe don't have space to go deep into that here,\nbut here's some documentation on ",[35,6089,6092],{"href":6090,"rel":6091,"target":40},"https:\u002F\u002Fmozilla.github.io\u002Funiffi-rs\u002Flatest\u002Ftypes\u002Fcustom_types.html",[39],"how you can do it","\nwithout using primitives as a lowest common denominator.",[24,6095,6096],{},"Finally, UniFFI makes it easy to use native code implementations\nof a protocol\u002Finterface with your Rust core!\nThis lets us do things like dependency injection in a type-safe manner\nacross an FFI boundary.",[28,6098,6100],{"id":6099},"what-are-the-rough-edges","What are the rough edges?",[24,6102,6103],{},"When I gave a talk about this three months ago at the Seoul Rust meetup,\nand I had an entire slide full of challenges.\nAlmost all of them were related to UDL,\nand almost are non-issues when you replace UDL generation with proc macros!\nA few remain though.",[24,6105,6106,6107,6110,6111,6113,6114,2686,6117,6120],{},"First, ",[62,6108,6109],{},"you'll need to change your habits around struct mutation",".\nSince we are introducing foreign code,\nUniFFI must assume that objects may be mutated from other threads.\nSo, you can't have mutable references to ",[349,6112,5273],{}," in UniFFI interfaces\nand must rely on interior mutability patterns instead.\nImportantly, your storage needs to be both ",[349,6115,6116],{},"Send",[349,6118,6119],{},"Sync",",\nwhich means you'll need to turn to things like atomics and mutexes.",[24,6122,6123,6124,6126,6127,6130],{},"UniFFI is also evolving quite rapidly.\nWhile some high-profile crates are fairly stable pre-1.0,\nyou can definitely expect some turbulence with UniFFI.\nThe changelogs are normally quite good,\nbut if you're tracking ",[349,6125,4428],{},"\nyou can expect breaking changes.\nFortunately, the team are ",[611,6128,6129],{},"super"," responsive on GitHub.\nThey're working on it every day, and are extremely responsive as maintainers\n(we submitted a PR to improve some docs around proc macros,\nand it was merged after a round of discussions in less than 24 hours).",[24,6132,6133],{},"The process of generating bindings for Swift and Kotlin,\nintegrating this into your build tooling,\nand packaging everything into a usable SPM \u002F Maven package\nis also quite complex.\nIn fact, we would even suggest that the best practices around this\nare still being explored.\nThis is a complex topic, and this post is already quite long,\nso we'll save it for the next article.",[28,6135,2554],{"id":2553},[24,6137,6138,6139,6143],{},"In summary, while it is still a developing field,\nwe couldn't be more excited about the future of Rust on mobile.\nAs we've shown in this post, a shared core is not just possible;\nit's actually pretty straightforward and the developer experience is great\nthanks to UniFFI.\nWe've put what we've learned into a\n",[35,6140,6142],{"href":2322,"rel":6141,"target":40},[39],"template repo","\nso you can try it too, without spending days figuring out boilerplate.",[24,6145,6146],{},"Stay tuned for the next post,\nwhere we'll dive deeper into build processes and packaging.\nYou can follow us on social media,\njoin our Slack or Discord communities,\nor subscribe to our mailing list (no spam)\nto get the news first.",[24,6148,6149,6150,6155],{},"Finally,\nif you're excited to bring the latest innovations in routing to more users,\ncheck out Ferrostar ",[35,6151,6154],{"href":6152,"rel":6153,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar",[39],"on GitHub",".\nWe have an issue tracker and have even marked some good first issues.\n(We'd especially love to have someone who is excited about Jetpack Compose.)\nLet's build the future of mobile navigation together!",[852,6157,6158],{},"html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}",{"title":168,"searchDepth":169,"depth":169,"links":6160},[6161,6162,6163,6164,6174,6175,6176],{"id":4121,"depth":172,"text":4122},{"id":4145,"depth":172,"text":4146},{"id":4202,"depth":172,"text":4203},{"id":4241,"depth":172,"text":4242,"children":6165},[6166,6167],{"id":4265,"depth":669,"text":4266},{"id":4600,"depth":669,"text":4601,"children":6168},[6169,6170,6171,6172,6173],{"id":4614,"depth":169,"text":4615},{"id":4734,"depth":169,"text":4735},{"id":4964,"depth":169,"text":4965},{"id":5506,"depth":169,"text":5507},{"id":5734,"depth":169,"text":5735},{"id":6070,"depth":172,"text":6071},{"id":6099,"depth":172,"text":6100},{"id":2553,"depth":172,"text":2554},"The first in a series of technical blog posts covering cross-platform mobile development in Rust.",[2588,2715,6179,2592,1795],"Navigation SDK",{"updated":6181},"2024-02-06","2023-11-15","---\ndescription: \"The first in a series of technical blog posts covering cross-platform mobile development in Rust.\"\npublished: \"2023-11-15\"\nupdated: \"2024-02-06\"\nkeywords:\n  - \"Rust\"\n  - \"Mobile Development\"\n  - \"Navigation SDK\"\n  - \"Cross-Platform Development\"\n  - \"Ferrostar\"\nschemaType: TechArticle\nproficiencyLevel: Expert\n---\n\n# Ferrostar: Building a Cross-Platform Navigation SDK in Rust (Part 1)\n\nThis is the first in a series of technical blog posts\ncovering the joys and challenges\nof building a cross-platform shared library,\nwith a focus on use in mobile applications.\n\nAs a motivating example to frame things,\nwe'll follow the journey of building Ferrostar,\na free and open-source navigation SDK.\nWe want to offer a modern SDK that is cross-platform,\nvendor-neutral, and easily extensible\nboth by direct contributors and developers using it in their apps.\n\n## Why?\n\nBefore we get into the technical weeds too much,\nit's worth taking a moment to ask _why_.\nAt Stadia Maps,\nwe have offered [highly customizable routing](\u002Fproducts\u002Frouting-navigation\u002F)\nsince 2017,\nand support use cases including safe pedestrian routing through lit areas,\ngolf cart routing that prefers multi-use paths,\nand more!\nBut developers are on their own\nwhen it comes to offering a turn-by-turn navigation UI.\nSeveral open-source apps already offer navigation,\nbut the solution is not generalized.\nAmong open-source navigation SDKs,\nMapLibre Navigation Android being the most mature at the time of this writing.\nBut as the name suggests, it is Android-specific.\nAnd since the internals originally came from old open-source Mapbox code,\nit takes considerable effort to use with other vendors,\nand extensibility was never a core design consideration.\n\nStarting a new navigation SDK is certainly an ambitious project,\nbut at the moment there is no navigation SDK that is\nhigh-quality, cross-platform, and open-source.\nWe're here to change that,\nand enable developers to bring these routing innovations to their users.\n\nThis post series is about the nuts and bolts of how we plan to pull it off.\nWe'll start with an overview of ways to share common logic across platforms,\nexplain the architecture we settled on,\nand finish with a deep dive into the first technical topic:\nbinding generation with [UniFFI](https:\u002F\u002Fmozilla.github.io\u002Funiffi-rs\u002F).\n\n## How to Share Common Logic?\n\nWe want to target multiple platforms: iOS and Android for starters.\nCertain code is the same regardless of where you're running it.\nAlgorithms like detecting if the user has strayed off the route\nand calculating the distance to the next turn\nshould be written once and shared across platforms.\nAnd at an even higher level,\nthe broad \"business logic\" of a turn-by-turn navigation experience\nshould be common shared code.\n\nBroadly speaking, there are two common approaches\nfor sharing code across platforms in mobile apps today.\nFirst, there are cross-platform app development frameworks like\nFlutter, React Native, or Kotlin Multiplatform.\nThey promise the ability to write your business logic and UI once\nand run it anywhere.\nThe second approach is to put your business logic in a shared library.\nYou write your code in a reasonably portable language (usually C++)\nand link this with your (platform-specific) applications.\n\nIn general,\nthe cross-platform frameworks are optimized for building *applications*,\nnot *libraries*.\nWe want to ensure that we can support additional platforms\nwith relative ease.\nYou can't just pick up React Native, for example,\nand run it on a bicycle computer.\nThis is situation is improving though.\nFor example, Flutter now runs on certain embedded devices,\nand Kotlin Multiplatform has a quickly improving support for library targets.\nHowever, these are still very early stage developments,\nand they involve a certain amount of ecosystem lock-in.\n\nGiven our requirements, we opted for the shared library approach.\nHistorically, C++ has been a popular choice for the task.\nIt is portable across a wide range of platforms,\ncan be made to interoperate with almost any other language,\nand usually produces small, well-optimized binaries.\nWe preferred to use something else for a few reasons,\nthe most important being\nthat it is difficult to write safe and correct C++ code,\nespecially as a new contributor.\n\nAt Stadia Maps, we have been shipping Rust in production since 2018.\nOur investment has rewarded us with\nconsistently good performance (Rust is keen on zero-cost abstractions),\nmemory safety,\nand excellent maintainability.\nAnd Rust code tends to have fewer bugs as well!\nRust also has excellent interoperability with other languages\nvia a straightforward FFI using the platform's C ABI,\nin stark contrast to C++ which can be rather complex to interface with.\nRust also has a large and growing list of supported platforms,\nincluding iOS and Android on several architectures.\n\nWe aren't alone in our selection of Rust either.\nWe've seen a lot of exciting development in Rust mobile frameworks\nlike [Crux](https:\u002F\u002Fredbadger.github.io\u002Fcrux\u002F),\n[Dioxus](https:\u002F\u002Fdioxuslabs.com\u002F),\nand [Rinf](https:\u002F\u002Fgithub.com\u002Fcunarist\u002Frinf) over the past year.\nBut it's not just new experimental projects that are adopting Rust.\nWe know that both [Mozilla](https:\u002F\u002Fwiki.mozilla.org\u002FOxidation)\nand [Lyft](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=e2ID05dpJzo)\nare using Rust shared libraries in their mobile apps.\nRust is already being used in production mobile apps today.\n\n## Architecture Overview\n\nZooming out, let's look at the broader architecture we adopted.\nThe core is the place where we want all shared logic to live.\nIn the context of our navigation SDK,\nthis includes parsing API responses,\nfiguring out when to advance navigation to the next step,\ncalculating the distance to the next turn,\nand so on.\n\nShared logic in a \"functional core\" isn't new,\nbut we can go one step further and define our data models too!\nThis lets us keep the navigation logic vendor- and platform-agnostic.\nFor example,\nwe define a common location update type with fields like\ncoordinate, timestamp, and heading.\nThis way the core logic doesn't need to care about the differences between\n`CLLocation` and `android.location.Location`.\n\nWe're building a Rust library that's callable via the C ABI.\nBut if we want any mobile devs to even try our framework,\nwe'll need to expose a nicer Swift\u002FKotlin interface.\nThese are called bindings,\nand they provide a thin layer that hides the messy details\nof going back and forth between Rust and the \"native\" mobile code.\n\nFinally, we have the native mobile library.\nThis is the only thing that most app developers will see,\nand it handles communications with the \"outside world\" (ex: internet and GPS),\nand provides a higher level API that can be a bit more \"opinionated.\"\nWe won't say much more about this layer in the rest of our discussions,\nas many volumes have been written on good API and library design.\n\n**Spoiler to avert anxiety and frantic typing**: the rest of this blog goes deep into\n\"how the sausage is made.\"\nTo save you the tedious work of reproducing the structure for your next library,\nwe've put together a [public template repo](https:\u002F\u002Fgithub.com\u002Fianthetechie\u002Funiffi-starter)\non GitHub which is ready to go with no typing or other fiddling required.\nWith that, let's dive in!\n\n![Ferrostar Architecture Diagram](\u002Fimages\u002Fcontent\u002Fferrostar-arch.png)\n\n## Bindings: Bridging Rust and Platform Code\n\nIf you're familiar with the concept of foreign function interfaces (FFIs),\nyou may remember `extern` declarations,\ncalling convention specifications,\nand having to write a lot of boilerplate.\nBut you know what is really good at generating boilerplate?\nComputers!\nEnter: binding generators.\n\nMozilla has developed a fantastic tool for binding generation:\n[UniFFI](https:\u002F\u002Fmozilla.github.io\u002Funiffi-rs\u002F).\nIn their case, the motivation was to build pieces of Firefox\nwhich could be shared across platforms.\nUniFFI is designed to generate safe bindings that feel idiomatic\nto users of the target language.\nThe [design principles](https:\u002F\u002Fmozilla.github.io\u002Funiffi-rs\u002Finternals\u002Fdesign_principles.html)\nof UniFFI aligned well with our requirements for Ferrostar,\nand we think they tend to be a good fit for most similar mobile use cases.\n\n### Cargo workspace setup\n\nLet's dive in with discussing the cargo workspace setup for Ferrostar.\nThis should be a helpful guide for anyone wanting to create their own\ncross-platform library.\n\nWe chose to structure the Rust portion of our library as a workspace\nwith two member projects: `uniffi-bindgen` and `ferrostar`.\nAt the time of this writing,\nthe ability to run the binary from the `uniffi` crate\nis only available in nightly,\nso we opted for a second `uniffi-bindgen` crate in our workspace\nfor the CLI binary.\nHere's what it looks like on disk:\n\n```\n├── Cargo.lock\n├── Cargo.toml\n├── ferrostar\n│   ├── Cargo.toml\n│   └── src\n│       └── lib.rs\n└── uniffi-bindgen\n    ├── Cargo.toml\n    └── src\n        └── main.rs\n```\n\nScaffolding in place, we need to add UniFFI to our workspace's `Cargo.toml`.\nThis way we can keep the binding generator and library versions in sync.\nAt the time this article was originally published,\nproc macro features were still under active development.\nSince then, they have stabilized somewhat,\nand it might make sense to start using the crates.io releases.\nIf you want the newest features and fixes though,\nit's best to use git dependencies.\nTracking the latest commits can cause pain,\nbut it is pretty rewarding if you want access to the latest improvements,\nwhich do come quite fast.\n\n```toml\n[workspace]\n\nmembers = [\n    \"uniffi-bindgen\",\n    \"ferrostar\",\n]\nresolver = \"2\"\n\n[workspace.dependencies]\nuniffi = \"0.26.1\"\n```\n\nThen, we can add it to the `uniffi-bindgen` and `ferrostar` crates respectively.\nIn the `uniffi-bindgen` crate, we need the `cli` feature.\n\n```toml\n[dependencies]\nuniffi = { workspace = true, features = [\"cli\"] }\n```\n\nThe `main` function in `uniffi-bindgen\u002Fsrc\u002Fmain.rs` is a single line.\nHere's the entire file:\n\n```rust\nfn main() {\n    uniffi::uniffi_bindgen_main()\n}\n```\n\nIn the `ferrostar` crate, we also need `uniffi` as a normal dependency\n*and* build dependency.\nWe also need to configure the library target with a few different\n[`crate_type`s](https:\u002F\u002Fdoc.rust-lang.org\u002Freference\u002Flinkage.html).\n\n* `cdylib` - A dynamic system library. Used on most platforms.\n* `staticlib` - A system library with *all* upstream dependencies included.\n  Required to target iOS.\n* `lib` - A Rust library.\n  This isn't mentioned in the UniFFI documentation as of this writing,\n  but if you want to add integration tests (runnable via `cargo test`)\n  and you don't include a Rust library target,\n  you'll get strange errors.\n\n```toml\n[dependencies]\nuniffi.workspace = true\n\n[build-dependencies]\nuniffi = { workspace = true, features = [\"build\"] }\n\n[lib]\ncrate-type = [\"cdylib\", \"staticlib\", \"lib\"]\n```\n\n### Defining what to export\n\nInternally, UniFFI uses an IDL (Interface Definition Language) to describe\nthe public interface of your crate to foreign code (ex: Swift and Kotlin).\nThis is similar to the process of writing a header file in C\nin that it is a set of definitions,\nbut the definition file is used to generate the foreign language bindings.\n\nThis used to require writing a bunch of boilerplate by hand.\nFortunately, UniFFI (starting from v0.25.0) automates this using procedural macros.\nFor our use case,\nwe were able to replace *all* handwritten UDL with macros,\nand expect this will be the best path for most library authors going forward.\n\n#### Functions\n\nLet's get started by exporting a function from Rust\nwhich generates a parser for routing data coming from our APIs.\nA single macro, `uniffi:export` is all we need to export a top-level function.\n\n```rust\n#[uniffi::export]\nfn create_osrm_response_parser(polyline_precision: u32) -> Arc\u003Cdyn RouteResponseParser> {\n    Arc::new(OsrmResponseParser::new(polyline_precision))\n}\n```\n\nUniFFI macros generate the definitions for us automatically\nbased on the function's type signature.\nMany built-in types like numbers, `String`, and `bool`\n\"just work\" as you expect.\nCollections like `Vec\u003CT>`, `Option\u003CT>` and `HashMap\u003CK, V>` are also implemented\nfor all types that UniFFI knows how to represent over the FFI.\nThey even have special cases for types like `Vec\u003Cu8>`\nwhich idiomatically map to a language-specific byte sequence type\n(ex: `Data` in Swift)!\n\nIf anything you export references a type\nthat UniFFI doesn't know how to convert,\nyou will get a compilation error.\nSo, how do we tell UniFFI about new types?\n\n#### Data models\n\nLet's look at two data models: user locations and route requests.\nWe'll export these using derive macros.\nIf you've used the `serde` crate, this should feel familiar.\n\nUser location is just a struct with some properties like coordinates\nand course over ground.\nThe `uniffi::Record` macro exposes our Rust types idiomatically.\nThey will show up as `struct`s in Swift, and `data class`es in Kotlin.\n\n```rust\n#[derive(uniffi::Record)]\npub struct UserLocation {\n    pub coordinates: GeographicCoordinates,\n    pub horizontal_accuracy: f64,\n    pub course_over_ground: Option\u003CCourseOverGround>,\n    pub timestamp: SystemTime,\n}\n```\n\nRoute requests are a little different.\nThey don't really map to a record type.\nSince we want to build an extensible framework,\nwe need to account for multiple ways of getting a route.\nFor example, making an HTTP request, or computing a route on-device.\n\nThis maps well to an enumeration.\nThe `uniffi::Enum` derive macro exports these like you would expect.\n\n```rust\n#[derive(uniffi::Enum)]\npub enum RouteRequest {\n    HttpPost {\n        url: String,\n        headers: HashMap\u003CString, String>,\n        body: Vec\u003Cu8>,\n    },\n    \u002F\u002F ...\n}\n```\n\n#### Objects\n\nYou can also export more complex objects\nwith local state, methods, and constructors!\n\nOne example of this in Ferrostar is our route adapter.\nIt stores a request generator and response parser\nand exposes a generic interface\nso the caller doesn't need to know about the details.\n\n```rust\n#[derive(uniffi::Object)]\npub struct RouteAdapter {\n    request_generator: Arc\u003Cdyn RouteRequestGenerator>,\n    response_parser: Arc\u003Cdyn RouteResponseParser>,\n}\n\n#[uniffi::export]\nimpl RouteAdapter {\n    #[uniffi::constructor]\n    pub fn new(\n        request_generator: Arc\u003Cdyn RouteRequestGenerator>,\n        response_parser: Arc\u003Cdyn RouteResponseParser>,\n    ) -> Self {\n        Self {\n            request_generator,\n            response_parser,\n        }\n    }\n\n    #[uniffi::constructor]\n    pub fn new_valhalla_http(endpoint_url: String, profile: String) -> Arc\u003CSelf> {\n        let request_generator = create_valhalla_request_generator(endpoint_url, profile);\n        let response_parser = create_osrm_response_parser(6);\n        Self::new(request_generator, response_parser)\n    }\n\n    pub fn generate_request(\n        &self,\n        user_location: UserLocation,\n        waypoints: Vec\u003CGeographicCoordinates>,\n    ) -> Result\u003CRouteRequest, RoutingRequestGenerationError> {\n        self.request_generator\n            .generate_request(user_location, waypoints)\n    }\n\n    pub fn parse_response(\n        &self,\n        response: Vec\u003Cu8>,\n    ) -> Result\u003CVec\u003CRoute>, RoutingResponseParseError> {\n        self.response_parser.parse_response(response)\n    }\n}\n```\n\nThis example is a bit more complicated than the others we've looked at so far.\nFirst, we use the `uniffi::Object` derive macro on the struct.\nIn contrast to `uniffi::Record`,\nthis signals that the type will be passed by reference and may have methods.\nThis will be exposed in Swift or Kotlin as a class.\n\nYou must annotate your constructors with the `uniffi::constructor` macro.\nAt the time of this writing, constructors must return an `Arc\u003CSelf>`.\nThe `new` constructor is special, and is exposed most naturally,\nbut other named constructors are also supported if you mark them as such.\nThey are not currently as idiomatic as the default constructor,\nbut I expect things like exposing a `convenience init` to Swift\nwill be possible in the future.\n\nFinally, types exported with `uniffi::Object` tell the binding generator\nto emit a `protocol` (Swift) or `interface` (Kotlin) definition.\n**Pro tip:** This makes it easier for you to write mock implementations\nfor unit testing!\nOur rule of thumb is to _pass_ the protocol\u002Finterface to your native methods,\nand define your instance variables with protocol\u002Finterface types.\nWhen the time comes to construct one,\nyour business logic will dictate which _concrete_ implementation to construct.\nThis makes your code significantly more extensible,\nand allows you to either use implementations from the Rust core\nor define your own in Swift\u002FKotlin.\n\n#### Errors\n\nResult types in Rust signal errors,\nand UniFFI can expose these idiomatically in the generated bindings.\nWe use this pattern in the above example to signal response parsing errors.\n\n```rust\n#[derive(Debug, thiserror::Error, uniffi::Error)]\npub enum RoutingResponseParseError {\n    #[error(\"Failed to parse route response: {error}.\")]\n    ParseError { error: String },\n    \u002F\u002F ...\n    #[error(\"An unknown error parsing a response was raised in foreign code.\")]\n    UnknownError,\n}\n```\n\nThe `uniffi::Error` derive macro will work with any type\nconforming to `std::Error`.\nWe make extensive use of `thiserror` for simplicity.\nIn Swift and Kotlin code,\nthis definition will be bridged into an enum conforming to `Error`\nand a sealed subclass of `Exception` respectively.\n\nBesides exposing the error types themselves,\nUniFFI also makes the error handling idiomatic.\nLet's return to the response parsing function signature.\n\n```rust\npub fn parse_response(\n    &self,\n    response: Vec\u003Cu8>,\n) -> Result\u003CVec\u003CRoute>, RoutingResponseParseError>\n```\n\nSemantically speaking,\nthis function will either return an ordered list of routes,\nor it will generate an error of type `RoutingResponseParseError`.\nAs such, this is how the generated Swift bindings will look:\n\n```swift\npublic func parseResponse(response: Data) throws -> [Route]\n```\n\nSwift does not explicitly list error types, but uses the `throws` keyword.\nIf you inspect the generated code,\nyou can see that UniFFI does indeed handle error variants,\nmapping them to your error types.\n\n#### Traits\n\nCarrying on the motivating use case of vendor-agnostic routing API integration,\nwe define traits in our crate for response parsing\nand similar things that we want to ensure remain generic.\n\n```rust\n#[uniffi::export(with_foreign)]\npub trait RouteResponseParser: Send + Sync {\n    \u002F\u002F\u002F Parses a raw response from the routing backend into a route.\n    fn parse_response(&self, response: Vec\u003Cu8>) -> Result\u003CVec\u003CRoute>, RoutingResponseParseError>;\n}\n```\n\nYou can export traits with the `uniffi::export` macro,\nand will they show up as protocols\u002Finterfaces in your foreign code.\nEven better, if you use `with_foreign`, you can supply foreign code to Rust!\nIt requires a bit of a dance Rust-side\n(you must use types of the form `Arc\u003Cdyn Trait>` at the time of this writing),\nbut that's a small price to pay for such flexibility.\n\nHere's what it looks like in Swift.\nFirst, the Rust `trait` is translated into a Swift `protocol` automatically\nby the UniFFI binding generator.\nThe method even has `throws`, just like you'd write in a pure Swift project!\n\n```swift\npublic protocol RouteResponseParser: AnyObject {\n    \u002F**\n     * Parses a raw response from the routing backend into a route.\n     *\n     * We use a sequence of octets as a common interchange format.\n     * as this works for all currently conceivable formats (JSON, PBF, etc.).\n     *\u002F\n    func parseResponse(response: Data) throws -> [Route]\n}\n```\n\nNow we can implement it just like any other protocol.\nHere's an example of an implementation that we use in our testing.\nIt's a mock that is initialized with a fixed set of routes for\n\"end-to-end\" tests without hitting a network service.\nIn the real world, you might use `Codable`\nto convert the raw data into a Swift model\nand then map it to Ferrostar `Route`s.\n\n```swift\nclass MockRouteResponseParser: RouteResponseParser {\n    private let routes: [Route]\n\n    init(routes: [Route]) {\n        self.routes = routes\n    }\n\n    func parseResponse(response _: Data) throws -> [Route] {\n        routes\n    }\n}\n```\n\nBy making things like `RouteRequestGenerator` and `RouteResponseParser` traits,\nwe make it possible for anyone to do the following:\n\n1. Connect to a custom routing server (for example, one they are self-hosting).\n2. Parse routes in a different format.\n3. Generate routes on-device (in another library, Swift, Kotlin, etc.).\n\nWe're really excited about how this will enable more innovation by developers,\nsince Ferrostar will be easily adaptable to custom routing backends,\nboth for research and commercial use.\n\n## What works well?\n\nThe APIs UniFFI generates truly feel idiomatic!\nIt's hard to overstate how nice this is.\nIt also goes out of its way to generate protocols\u002Finterfaces,\nwhich make it easy to mock parts for unit testing in native code,\nand even has pleasant surprises\nlike `Vec\u003Cu8>` mapping to idiomatic byte sequence types.\n\nUniFFI encourages good hygiene all the way from Rust to your application code\nvia type safety.\nAny type that appears in your signature must be exported,\nso you get checks from end to end.\nAnd Rust functions that return a `Result` type\nare translated into idiomatic errors and exceptions.\n\nYou can even bridge custom types!\nWe don't have space to go deep into that here,\nbut here's some documentation on [how you can do it](https:\u002F\u002Fmozilla.github.io\u002Funiffi-rs\u002Flatest\u002Ftypes\u002Fcustom_types.html)\nwithout using primitives as a lowest common denominator.\n\nFinally, UniFFI makes it easy to use native code implementations\nof a protocol\u002Finterface with your Rust core!\nThis lets us do things like dependency injection in a type-safe manner\nacross an FFI boundary.\n\n## What are the rough edges?\n\nWhen I gave a talk about this three months ago at the Seoul Rust meetup,\nand I had an entire slide full of challenges.\nAlmost all of them were related to UDL,\nand almost are non-issues when you replace UDL generation with proc macros!\nA few remain though.\n\nFirst, **you'll need to change your habits around struct mutation**.\nSince we are introducing foreign code,\nUniFFI must assume that objects may be mutated from other threads.\nSo, you can't have mutable references to `self` in UniFFI interfaces\nand must rely on interior mutability patterns instead.\nImportantly, your storage needs to be both `Send` and `Sync`,\nwhich means you'll need to turn to things like atomics and mutexes.\n\nUniFFI is also evolving quite rapidly.\nWhile some high-profile crates are fairly stable pre-1.0,\nyou can definitely expect some turbulence with UniFFI.\nThe changelogs are normally quite good,\nbut if you're tracking `main`\nyou can expect breaking changes.\nFortunately, the team are _super_ responsive on GitHub.\nThey're working on it every day, and are extremely responsive as maintainers\n(we submitted a PR to improve some docs around proc macros,\nand it was merged after a round of discussions in less than 24 hours).\n\nThe process of generating bindings for Swift and Kotlin,\nintegrating this into your build tooling,\nand packaging everything into a usable SPM \u002F Maven package\nis also quite complex.\nIn fact, we would even suggest that the best practices around this\nare still being explored.\nThis is a complex topic, and this post is already quite long,\nso we'll save it for the next article.\n\n## Wrap-up\n\nIn summary, while it is still a developing field,\nwe couldn't be more excited about the future of Rust on mobile.\nAs we've shown in this post, a shared core is not just possible;\nit's actually pretty straightforward and the developer experience is great\nthanks to UniFFI.\nWe've put what we've learned into a\n[template repo](https:\u002F\u002Fgithub.com\u002Fianthetechie\u002Funiffi-starter)\nso you can try it too, without spending days figuring out boilerplate.\n\nStay tuned for the next post,\nwhere we'll dive deeper into build processes and packaging.\nYou can follow us on social media,\njoin our Slack or Discord communities,\nor subscribe to our mailing list (no spam)\nto get the news first.\n\nFinally,\nif you're excited to bring the latest innovations in routing to more users,\ncheck out Ferrostar [on GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fferrostar).\nWe have an issue tracker and have even marked some good first issues.\n(We'd especially love to have someone who is excited about Jetpack Compose.)\nLet's build the future of mobile navigation together!\n",{"title":4107,"description":6177},"blog\u002Fferrostar-building-a-cross-platform-navigation-sdk-in-rust-part-1","yNwBxFXqRcgsCQkfAB5UKiyb1KjlOrw9DsCn_z6-0M0",{"id":6188,"title":6189,"abstract":7,"author":7,"body":6190,"description":6273,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":6274,"meta":6278,"modified":7,"navigation":187,"path":6279,"proficiencyLevel":7,"published":6280,"rawbody":6281,"schemaOrg":7,"schemaType":7,"seo":6282,"stem":6283,"__hash__":6284},"blog\u002Fblog\u002Fsponsorships-osmf-openaddresses.md","Sponsorship of Two Open Data Projects",{"type":14,"value":6191,"toc":6270},[6192,6195,6213,6226,6229,6233],[17,6193,6189],{"id":6194},"sponsorship-of-two-open-data-projects",[24,6196,6197,6198,2616,6203,6207,6208,458],{},"Stadia Maps leverages open-source mapping technologies and datasets.  Since our inception, we have continually\ncontributed our technical expertise back to several projects, including ",[35,6199,6202],{"href":6200,"rel":6201,"target":40},"https:\u002F\u002Fvalhalla.github.io\u002Fvalhalla\u002F",[39],"Valhalla",[35,6204,2746],{"href":6205,"rel":6206,"target":40},"https:\u002F\u002Fmaplibre.org",[39],", as well as open-sourcing some ",[35,6209,6212],{"href":6210,"rel":6211,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps",[39],"projects of our own",[24,6214,6215,6216,6221,6222,458],{},"We are happy to announce our financial support for two organizations, whose work we both rely on and contribute back to: the\n",[35,6217,6220],{"href":6218,"rel":6219,"target":40},"https:\u002F\u002Fosmfoundation.org\u002F",[39],"OpenStreetMap Foundation"," (Bronze level) and ",[35,6223,404],{"href":6224,"rel":6225,"target":40},"https:\u002F\u002Fopenaddresses.io",[39],[24,6227,6228],{},"We take pride in contributing monetarily to these organizations, playing our role in helping secure their future.",[28,6230,6232],{"id":6231},"learn-more-about-stadia-maps","Learn More About Stadia Maps",[56,6234,6235,6243,6250],{},[59,6236,6237,6238,458],{},"Read more about the ",[35,6239,6242],{"href":6240,"rel":6241,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002F",[39],"products we offer at Stadia Maps",[59,6244,6245,6249],{},[35,6246,1720],{"href":6247,"rel":6248,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=sponsor_organizations&utm_content=sponsorship_osfm_openaddresses",[39]," to start building today!",[59,6251,1231,6252,1056,6255,3448,6258,352,6261,1749,6264,1753,6267,3461],{},[35,6253,1239],{"href":1237,"rel":6254,"target":40},[39],[35,6256,849],{"href":847,"rel":6257,"target":40},[39],[35,6259,1248],{"href":1246,"rel":6260,"target":40},[39],[35,6262,1253],{"href":1251,"rel":6263,"target":40},[39],[35,6265,1264],{"href":1262,"rel":6266,"target":40},[39],[35,6268,1270],{"href":1268,"rel":6269,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":6271},[6272],{"id":6231,"depth":172,"text":6232},"We continue our support of the open-source community by sponsoring two organizations: The OpenStreetMap Foundation and OpenAddresses.",[6275,181,404,6276,6277],"Open Source","Sponsorship","Community",{},"\u002Fblog\u002Fsponsorships-osmf-openaddresses","2023-09-04","---\ndescription: \"We continue our support of the open-source community by sponsoring two organizations: The OpenStreetMap Foundation and OpenAddresses.\"\npublished: \"2023-09-04\"\nkeywords:\n  - Open Source\n  - OpenStreetMap\n  - OpenAddresses\n  - Sponsorship\n  - Community\n---\n\n# Sponsorship of Two Open Data Projects\n\nStadia Maps leverages open-source mapping technologies and datasets.  Since our inception, we have continually\ncontributed our technical expertise back to several projects, including [Valhalla](https:\u002F\u002Fvalhalla.github.io\u002Fvalhalla\u002F)\nand [MapLibre](https:\u002F\u002Fmaplibre.org), as well as open-sourcing some [projects of our own](https:\u002F\u002Fgithub.com\u002Fstadiamaps).\n\nWe are happy to announce our financial support for two organizations, whose work we both rely on and contribute back to: the \n[OpenStreetMap Foundation](https:\u002F\u002Fosmfoundation.org\u002F) (Bronze level) and [OpenAddresses](https:\u002F\u002Fopenaddresses.io).\n\nWe take pride in contributing monetarily to these organizations, playing our role in helping secure their future.\n\n## Learn More About Stadia Maps\n\n- Read more about the [products we offer at Stadia Maps](https:\u002F\u002Fstadiamaps.com\u002Fproducts\u002F).\n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=sponsor_organizations&utm_content=sponsorship_osfm_openaddresses) to start building today!\n- Join our community on [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) or [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT), follow us\non [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps), or\n[LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD)!\n",{"title":6189,"description":6273},"blog\u002Fsponsorships-osmf-openaddresses","_S__JbPTIDwhPOcE0TfH9reEbiGONiL5OnhP9vADhqM",{"id":6286,"title":6287,"abstract":7,"author":7,"body":6288,"description":6424,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":6425,"meta":6431,"modified":7,"navigation":187,"path":6432,"proficiencyLevel":7,"published":6433,"rawbody":6434,"schemaOrg":7,"schemaType":7,"seo":6435,"stem":6436,"__hash__":6437},"blog\u002Fblog\u002Fstamen-design-and-stadia-maps.md","Stamen Design × Stadia Maps",{"type":14,"value":6289,"toc":6415},[6290,6293,6305,6311,6327,6331,6345,6349,6356,6360,6363,6367,6376,6380,6383,6387,6394,6399,6402],[17,6291,6287],{"id":6292},"stamen-design-stadia-maps",[24,6294,6295,6296,6301,6302,458],{},"Today, Stadia Maps and ",[35,6297,6300],{"href":6298,"rel":6299,"target":40},"https:\u002F\u002Fstamen.com",[39],"Stamen Design"," are pleased to announce a long-term partnership. Together, we\nwill build mapping services that pair Stamen’s world-class cartography and Stadia Maps’ location platform to make great\nmaps accessible to ",[611,6303,6304],{},"everyone",[24,6306,6307,6308,6310],{},"Historically, this level of cartographic excellence has been reserved for those with deep pockets—but no longer!\nBuilding on the foundational work of open data and open source, our strengths combine to crate a new class of map\nservice: maps that are world-class in design and data ",[611,6309,4481],{}," affordable, private, and fully backed by the reliable\ninfrastructure and responsive support.",[6312,6313,6314,6315,6314,6321],"figure",{},"\n    ",[1810,6316],{"alt":6317,"style":6318,"src":6319,"title":6320},"Stamen Tiles","height: 250px; width: 100%; object-fit: cover;","\u002Fimages\u002Fcontent\u002Fstamen_x_stadia.jpg","Stamen Map Tiles",[6322,6323,6326],"figcaption",{"className":6324},[6325],"is-size-6","The original map tiles. Map tiles by Stamen Design, under CC BY 4.0. Data by OpenStreetMap contributors.",[28,6328,6330],{"id":6329},"stamen-map-tiles-on-stadia-maps","Stamen Map Tiles on Stadia Maps",[24,6332,6333,6334,6339,6340,458],{},"During this first phase of our partnership, we're launching maps based on the widely-used Stamen map tiles.\nThese include the Stamen Watercolor, Stamen Terrain, and Stamen Toner styles that have been\non ",[35,6335,6338],{"href":6336,"rel":6337,"target":40},"http:\u002F\u002Fmaps.stamen.com",[39],"maps.stamen.com"," for years as a free, unsupported tile service. Since launch, these map\ntiles have found their way into dozens of open source libraries, thousands of projects, and even\nthe ",[35,6341,6344],{"href":6342,"rel":6343,"target":40},"https:\u002F\u002Fwww.si.edu\u002Fnewsdesk\u002Freleases\u002Fwatercolor-maptiles-website-enters-permanent-collection-cooper-hewitt",[39],"Smithsonian’s permanent collection",[1205,6346,6348],{"id":6347},"refreshed-styles-modern-tooling-and-a-proven-platform","Refreshed Styles, Modern Tooling, and a Proven Platform",[24,6350,6351,6352,6355],{},"As part of this launch, we reworked and refreshed the styles. Stamen rebuilt them from scratch on the\nmodern ",[35,6353,2746],{"href":6205,"rel":6354,"target":40},[39]," mapping stack. Stadia Maps is serving them using their up-to-date, detailed map\ndata. As with all of Stadia Maps’ services, these map tiles will come with all the same real human support and\ncontractual guarantees, including optional SLAs.",[1205,6357,6359],{"id":6358},"flexible-extensible","Flexible & Extensible",[24,6361,6362],{},"By rebuilding the styles using modern tooling, we can offer map tiles for vector- or raster-based libraries, with the\nfull flexibility and customization allowed by vector styling. Users will be able to adjust colors, remove and reorder\nlayers, change the default language, and mix-in their own data with ease.",[1205,6364,6366],{"id":6365},"get-started-with-stamen-tiles-on-stadia-maps","Get Started with Stamen Tiles on Stadia Maps",[24,6368,6369,6370,6375],{},"If you're an existing user of Stamen map tiles, you can learn all you need to know in\nour ",[35,6371,6374],{"href":6372,"rel":6373,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fguides\u002Fmigrating-from-stamen-map-tiles\u002F",[39],"Stamen map tiles migration guide",". If you're a\nnew user, you'll just need to create an account and start using the style URLs found in the same guide. Instructions for\nvector map styles will be released soon.",[28,6377,6379],{"id":6378},"the-future","The Future",[24,6381,6382],{},"This is phase one, and we're just getting started. Together, we intend to launch more products and services based on our\ncomplimentary expertise—all on a mission to make world-class cartography accessible to everyone.",[28,6384,6386],{"id":6385},"more-about-stamen-design-stadia-maps","More about Stamen Design & Stadia Maps",[24,6388,6389,6390,6393],{},"Since the beginning, quality cartography as been part of Stadia Maps’ DNA. We set out to build a map that was\naffordable, private, and, most of all, ",[611,6391,6392],{},"looked good",". In the past seven years, we’ve succeeded\nat that and more. You can find our maps, alongside our search, routing, and many other services, at the heart of\nhundreds’ of products and used by thousands of developers around the world.",[24,6395,6396,6397,458],{},"You can reach Stadia Maps via email at ",[35,6398,3839],{"href":3838},[24,6400,6401],{},"For the past 20 years, Stamen has helped companies (including Meta, Amazon, and National Geographic), NGOs (including\nthe Dalai Lama and museums around the world), and individuals build beautiful and usable maps. Stamen is an early\nproponent of using OSM map data to create good maps, and when you look at almost every significant OSM-based mapping\nproject in the last decade, they—or their alumni—have played instrumental parts.",[24,6403,6404,6405,6409,6410,458],{},"You can reach Stamen directly via email at ",[35,6406,6408],{"href":6407},"mailto:info@stamen.com","info@stamen.com"," or via\ntheir ",[35,6411,6414],{"href":6412,"rel":6413,"target":40},"https:\u002F\u002Fstamen.com\u002Fcontact\u002F",[39],"contact form",{"title":168,"searchDepth":169,"depth":169,"links":6416},[6417,6422,6423],{"id":6329,"depth":172,"text":6330,"children":6418},[6419,6420,6421],{"id":6347,"depth":669,"text":6348},{"id":6358,"depth":669,"text":6359},{"id":6365,"depth":669,"text":6366},{"id":6378,"depth":172,"text":6379},{"id":6385,"depth":172,"text":6386},"Stadia Maps and Stamen Design are pleased to announce a long-term partnership to build mapping services to make great maps accessible to everyone.",[6300,6426,6427,6428,6429,6430],"Partnership","Map Styles","Cartography","Watercolor Maps","Toner Maps",{},"\u002Fblog\u002Fstamen-design-and-stadia-maps","2023-07-27","---\ndescription: >-\n  Stadia Maps and Stamen Design are pleased to announce a long-term partnership to build mapping services to make great maps accessible to everyone.\npublished: \"2023-07-27\"\nkeywords:\n  - Stamen Design\n  - Partnership\n  - Map Styles\n  - Cartography\n  - Watercolor Maps\n  - Toner Maps\n---\n\n# Stamen Design &times; Stadia Maps\n\nToday, Stadia Maps and [Stamen Design](https:\u002F\u002Fstamen.com) are pleased to announce a long-term partnership. Together, we\nwill build mapping services that pair Stamen’s world-class cartography and Stadia Maps’ location platform to make great\nmaps accessible to *everyone*.\n\nHistorically, this level of cartographic excellence has been reserved for those with deep pockets—but no longer!\nBuilding on the foundational work of open data and open source, our strengths combine to crate a new class of map\nservice: maps that are world-class in design and data *and* affordable, private, and fully backed by the reliable\ninfrastructure and responsive support.\n\n\u003Cfigure>\n    \u003Cimg alt=\"Stamen Tiles\" style=\"height: 250px; width: 100%; object-fit: cover;\" src=\"\u002Fimages\u002Fcontent\u002Fstamen_x_stadia.jpg\" title=\"Stamen Map Tiles\"\u002F>\n    \u003Cfigcaption class=\"is-size-6\">The original map tiles. Map tiles by Stamen Design, under CC BY 4.0. Data by OpenStreetMap contributors.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\n\n## Stamen Map Tiles on Stadia Maps\n\nDuring this first phase of our partnership, we're launching maps based on the widely-used Stamen map tiles.\nThese include the Stamen Watercolor, Stamen Terrain, and Stamen Toner styles that have been\non [maps.stamen.com](http:\u002F\u002Fmaps.stamen.com) for years as a free, unsupported tile service. Since launch, these map\ntiles have found their way into dozens of open source libraries, thousands of projects, and even\nthe [Smithsonian’s permanent collection](https:\u002F\u002Fwww.si.edu\u002Fnewsdesk\u002Freleases\u002Fwatercolor-maptiles-website-enters-permanent-collection-cooper-hewitt).\n\n### Refreshed Styles, Modern Tooling, and a Proven Platform\n\nAs part of this launch, we reworked and refreshed the styles. Stamen rebuilt them from scratch on the\nmodern [MapLibre](https:\u002F\u002Fmaplibre.org) mapping stack. Stadia Maps is serving them using their up-to-date, detailed map\ndata. As with all of Stadia Maps’ services, these map tiles will come with all the same real human support and\ncontractual guarantees, including optional SLAs.\n\n### Flexible & Extensible\n\nBy rebuilding the styles using modern tooling, we can offer map tiles for vector- or raster-based libraries, with the\nfull flexibility and customization allowed by vector styling. Users will be able to adjust colors, remove and reorder\nlayers, change the default language, and mix-in their own data with ease.\n\n### Get Started with Stamen Tiles on Stadia Maps\n\nIf you're an existing user of Stamen map tiles, you can learn all you need to know in\nour [Stamen map tiles migration guide](https:\u002F\u002Fdocs.stadiamaps.com\u002Fguides\u002Fmigrating-from-stamen-map-tiles\u002F). If you're a\nnew user, you'll just need to create an account and start using the style URLs found in the same guide. Instructions for\nvector map styles will be released soon.\n\n## The Future\n\nThis is phase one, and we're just getting started. Together, we intend to launch more products and services based on our\ncomplimentary expertise—all on a mission to make world-class cartography accessible to everyone.\n\n## More about Stamen Design & Stadia Maps\n\nSince the beginning, quality cartography as been part of Stadia Maps’ DNA. We set out to build a map that was\naffordable, private, and, most of all, *looked good*. In the past seven years, we’ve succeeded\nat that and more. You can find our maps, alongside our search, routing, and many other services, at the heart of\nhundreds’ of products and used by thousands of developers around the world.\n\nYou can reach Stadia Maps via email at [support@stadiamaps.com](mailto:support@stadiamaps.com).\n\nFor the past 20 years, Stamen has helped companies (including Meta, Amazon, and National Geographic), NGOs (including\nthe Dalai Lama and museums around the world), and individuals build beautiful and usable maps. Stamen is an early\nproponent of using OSM map data to create good maps, and when you look at almost every significant OSM-based mapping\nproject in the last decade, they—or their alumni—have played instrumental parts.\n\nYou can reach Stamen directly via email at [info@stamen.com](mailto:info@stamen.com) or via\ntheir [contact form](https:\u002F\u002Fstamen.com\u002Fcontact\u002F).\n",{"title":6287,"description":6424},"blog\u002Fstamen-design-and-stadia-maps","9mUJe2OICajz-JFfMzUte02qGPQ2GbXY6ssFcu3-Iu8",{"id":6439,"title":6440,"abstract":7,"author":7,"body":6441,"description":6579,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":6580,"meta":6584,"modified":7,"navigation":187,"path":6585,"proficiencyLevel":7,"published":6586,"rawbody":6587,"schemaOrg":7,"schemaType":7,"seo":6588,"stem":6589,"__hash__":6590},"blog\u002Fblog\u002Fnew-sdk-swift.md","New SDK for Swift is Now Available",{"type":14,"value":6442,"toc":6572},[6443,6446,6454,6457,6461,6464,6490,6498,6502,6505,6519,6521,6524,6528,6535,6537],[17,6444,6440],{"id":6445},"new-sdk-for-swift-is-now-available",[24,6447,6448,6449,6453],{},"Today we are excited to announce the initial release of our ",[35,6450,4076],{"href":6451,"rel":6452,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fswift\u002F",[39]," SDK.",[24,6455,6456],{},"Xcode users will get all the goodies like autocomplete, type definitions, and documentation as you type. All API methods\nleverage the async features introduced in Swift 5.5, which make it easier than ever to write correct asynchronous code.\nAnd since it's generated from official OpenAPI spec, you'll be among the first to get access to our latest features.",[28,6458,6460],{"id":6459},"weve-listened-and-delivered","We've Listened and Delivered",[24,6462,6463],{},"With this latest addition, we now support multiple languages and platform types:",[56,6465,6466,6473,6479,6485],{},[59,6467,6468],{},[35,6469,6472],{"href":6470,"rel":6471,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fjavascript-typescript\u002F",[39],"JavaScript\u002FTypeScript",[59,6474,6475],{},[35,6476,4083],{"href":6477,"rel":6478,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fkotlin-jvm\u002F",[39],[59,6480,6481],{},[35,6482,4090],{"href":6483,"rel":6484,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fpython\u002F",[39],[59,6486,6487],{},[35,6488,4076],{"href":6451,"rel":6489,"target":40},[39],[24,6491,6492,6493,458],{},"We also have a ",[35,6494,6497],{"href":6495,"rel":6496,"target":40},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@stadiamaps\u002Fmaplibre-search-box",[39],"MapLibre GL JS search box plugin",[28,6499,6501],{"id":6500},"why-use-the-sdks","Why Use the SDKs?",[24,6503,6504],{},"Of course you could write your code to directly interface with our APIs, but there are several benefits to taking\nadvantage of our SDKs:",[56,6506,6507,6510,6513,6516],{},[59,6508,6509],{},"Save time; no need to write your own API code since you have access to the full range of Stadia Maps geospatial APIs",[59,6511,6512],{},"Easily install via your favorite package manager",[59,6514,6515],{},"Faster access to documentation in your IDE with autocomplete",[59,6517,6518],{},"Always utilize the latest features because when we release a new API, we'll release an updated SDK",[28,6520,3396],{"id":3395},[24,6522,6523],{},"Since this is the initial version of the Swift SDK, we are looking for feedback from the community on updates, features,\nand improvements that we can incorporate into upcoming releases.",[28,6525,6527],{"id":6526},"where-to-find","Where to Find",[24,6529,6530,6531,458],{},"You can find the Swift SDK, and its source code, on\n",[35,6532,2818],{"href":6533,"rel":6534,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-swift",[39],[28,6536,1711],{"id":1710},[56,6538,6539,6546,6552],{},[59,6540,6541,6542,6545],{},"Read documentation about our ",[35,6543,1159],{"href":1482,"rel":6544,"target":40},[39]," and Plugins on our docs site.",[59,6547,6548,6249],{},[35,6549,1720],{"href":6550,"rel":6551,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=sdk_launch&utm_content=swift_sdk_announcement",[39],[59,6553,1231,6554,1056,6557,3448,6560,352,6563,1749,6566,1753,6569,3461],{},[35,6555,1239],{"href":1237,"rel":6556,"target":40},[39],[35,6558,849],{"href":847,"rel":6559,"target":40},[39],[35,6561,1248],{"href":1246,"rel":6562,"target":40},[39],[35,6564,1253],{"href":1251,"rel":6565,"target":40},[39],[35,6567,1264],{"href":1262,"rel":6568,"target":40},[39],[35,6570,1270],{"href":1268,"rel":6571,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":6573},[6574,6575,6576,6577,6578],{"id":6459,"depth":172,"text":6460},{"id":6500,"depth":172,"text":6501},{"id":3395,"depth":172,"text":3396},{"id":6526,"depth":172,"text":6527},{"id":1710,"depth":172,"text":1711},"Helping iOS developers build modern mapping experiences even faster with Stadia Map SDKs.",[6581,2589,6582,6583],"Swift SDK","Xcode","Mobile SDK",{},"\u002Fblog\u002Fnew-sdk-swift","2023-07-20","---\ndescription: \"Helping iOS developers build modern mapping experiences even faster with Stadia Map SDKs.\"\npublished: \"2023-07-20\"\nkeywords:\n  - Swift SDK\n  - iOS Development\n  - Xcode\n  - Mobile SDK\n---\n\n# New SDK for Swift is Now Available\n\nToday we are excited to announce the initial release of our [Swift](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fswift\u002F) SDK.\n\nXcode users will get all the goodies like autocomplete, type definitions, and documentation as you type. All API methods\nleverage the async features introduced in Swift 5.5, which make it easier than ever to write correct asynchronous code.\nAnd since it's generated from official OpenAPI spec, you'll be among the first to get access to our latest features.\n\n## We've Listened and Delivered\n\nWith this latest addition, we now support multiple languages and platform types:\n\n* [JavaScript\u002FTypeScript](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fjavascript-typescript\u002F)\n* [Kotlin](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fkotlin-jvm\u002F)\n* [Python](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fpython\u002F)\n* [Swift](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fswift\u002F)\n\nWe also have a [MapLibre GL JS search box plugin](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@stadiamaps\u002Fmaplibre-search-box).\n\n## Why Use the SDKs?\n\nOf course you could write your code to directly interface with our APIs, but there are several benefits to taking\nadvantage of our SDKs:\n\n* Save time; no need to write your own API code since you have access to the full range of Stadia Maps geospatial APIs\n* Easily install via your favorite package manager\n* Faster access to documentation in your IDE with autocomplete\n* Always utilize the latest features because when we release a new API, we'll release an updated SDK\n\n## We Want Your Feedback\n\nSince this is the initial version of the Swift SDK, we are looking for feedback from the community on updates, features,\nand improvements that we can incorporate into upcoming releases.\n\n## Where to Find\n\nYou can find the Swift SDK, and its source code, on\n[GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-swift).\n\n## Learn More & Next Steps\n\n- Read documentation about our [SDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F) and Plugins on our docs site.\n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=sdk_launch&utm_content=swift_sdk_announcement) to start building today!\n- Join our community on [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) or [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT), follow us\non [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps), or\n[LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD)!\n\n",{"title":6440,"description":6579},"blog\u002Fnew-sdk-swift","eitT75JQ5nnsdlKU2JyckTUl83DN1bNdZGp5ZyJMUx8",{"id":6592,"title":6593,"abstract":7,"author":7,"body":6594,"description":6675,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":6676,"meta":6680,"modified":7,"navigation":187,"path":6681,"proficiencyLevel":7,"published":6682,"rawbody":6683,"schemaOrg":7,"schemaType":7,"seo":6684,"stem":6685,"__hash__":6686},"blog\u002Fblog\u002Fupdate-to-geocoding-autocomplete-search.md","Major Update to Our Geocoding and Autocomplete Search Data",{"type":14,"value":6595,"toc":6668},[6596,6599,6607,6610,6614,6617,6621,6624,6628,6631,6633],[17,6597,6593],{"id":6598},"major-update-to-our-geocoding-and-autocomplete-search-data",[24,6600,6601,6602,458],{},"We just updated the underlying data for our recent\n",[35,6603,6606],{"href":6604,"rel":6605,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Foverview\u002F",[39],"Geocoding and Autocomplete Search APIs",[24,6608,6609],{},"With this release, our city and postal code data for over 50 million US addresses has significantly improved in terms of\ncompleteness, accuracy, and searchability.",[28,6611,6613],{"id":6612},"improved-quality-and-what-this-means-for-users","Improved Quality and What This Means for Users",[24,6615,6616],{},"These improvements offer distinct advantages compared to our competitors' similar APIs in two key areas:",[1205,6618,6620],{"id":6619},"enhanced-address-formatting","Enhanced Address Formatting",[24,6622,6623],{},"The results for US addresses will now more closely align with the preferred format recognized by the United States\nPostal Service, ensuring greater consistency and accuracy in address representation.",[1205,6625,6627],{"id":6626},"improved-searchability","Improved Searchability",[24,6629,6630],{},"When searching for addresses that have multiple colloquially used city names, users can effectively find the desired\naddresses by using these additional names, improving your search capabilities and overall user experience.",[28,6632,1711],{"id":1710},[56,6634,6635,6642,6648],{},[59,6636,6637,6638,6641],{},"Read documentation about our\n",[35,6639,6606],{"href":6604,"rel":6640,"target":40},[39]," docs site.",[59,6643,6644,6249],{},[35,6645,1720],{"href":6646,"rel":6647,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_launch&utm_content=geocoding_updates_july",[39],[59,6649,1231,6650,1056,6653,3448,6656,352,6659,1749,6662,1753,6665,3461],{},[35,6651,1239],{"href":1237,"rel":6652,"target":40},[39],[35,6654,849],{"href":847,"rel":6655,"target":40},[39],[35,6657,1248],{"href":1246,"rel":6658,"target":40},[39],[35,6660,1253],{"href":1251,"rel":6661,"target":40},[39],[35,6663,1264],{"href":1262,"rel":6664,"target":40},[39],[35,6666,1270],{"href":1268,"rel":6667,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":6669},[6670,6674],{"id":6612,"depth":172,"text":6613,"children":6671},[6672,6673],{"id":6619,"depth":669,"text":6620},{"id":6626,"depth":669,"text":6627},{"id":1710,"depth":172,"text":1711},"We have improved over 50 million US addresses' completeness, accuracy, and searchability.",[402,2714,6677,6678,6679],"Address Data","US Addresses","Data Update",{},"\u002Fblog\u002Fupdate-to-geocoding-autocomplete-search","2023-07-19","---\ndescription: \"We have improved over 50 million US addresses' completeness, accuracy, and searchability.\"\npublished: \"2023-07-19\"\nkeywords:\n  - Geocoding\n  - Autocomplete\n  - Address Data\n  - US Addresses\n  - Data Update\n---\n\n# Major Update to Our Geocoding and Autocomplete Search Data\n\nWe just updated the underlying data for our recent\n[Geocoding and Autocomplete Search APIs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Foverview\u002F).\n\nWith this release, our city and postal code data for over 50 million US addresses has significantly improved in terms of\ncompleteness, accuracy, and searchability.\n\n## Improved Quality and What This Means for Users\n\nThese improvements offer distinct advantages compared to our competitors' similar APIs in two key areas:\n\n### Enhanced Address Formatting\n\nThe results for US addresses will now more closely align with the preferred format recognized by the United States\nPostal Service, ensuring greater consistency and accuracy in address representation.\n\n### Improved Searchability\n\nWhen searching for addresses that have multiple colloquially used city names, users can effectively find the desired\naddresses by using these additional names, improving your search capabilities and overall user experience.\n\n## Learn More & Next Steps\n\n- Read documentation about our\n[Geocoding and Autocomplete Search APIs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Foverview\u002F) docs site.\n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_launch&utm_content=geocoding_updates_july) to start building today!\n- Join our community on [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) or [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT), follow us\non [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps), or\n[LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD)!",{"title":6593,"description":6675},"blog\u002Fupdate-to-geocoding-autocomplete-search","NMty06qHpCeX6Kyru__KhQRH8AzvoDabJCItKd5YYn0",{"id":6688,"title":6689,"abstract":7,"author":7,"body":6690,"description":6861,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":6862,"meta":6865,"modified":7,"navigation":187,"path":6866,"proficiencyLevel":7,"published":6867,"rawbody":6868,"schemaOrg":7,"schemaType":7,"seo":6869,"stem":6870,"__hash__":6871},"blog\u002Fblog\u002Fnew-sdks-and-maplibre-plugin.md","Three New SDKs and MapLibre GL JS Search Plugin Are Now Available",{"type":14,"value":6691,"toc":6853},[6692,6695,6712,6714,6717,6719,6721,6731,6735,6738,6741,6744,6758,6760,6763,6765,6768,6818,6820],[17,6693,6689],{"id":6694},"three-new-sdks-and-maplibre-gl-js-search-plugin-are-now-available",[24,6696,6697,6698,437,6701,356,6704,6707,6708,6711],{},"Today we are excited to announce the initial release of three SDKs (",[35,6699,6472],{"href":6470,"rel":6700,"target":40},[39],[35,6702,4090],{"href":6483,"rel":6703,"target":40},[39],[35,6705,4083],{"href":6477,"rel":6706,"target":40},[39],"), along\nwith a ",[35,6709,6497],{"href":6495,"rel":6710,"target":40},[39]," for Stadia\nMaps services.",[28,6713,6460],{"id":6459},[24,6715,6716],{},"These four projects round out our support for a large portion of our existing user base, including all browser-based\napps and many popular backend use cases too.",[28,6718,6501],{"id":6500},[24,6720,6504],{},[56,6722,6723,6725,6727,6729],{},[59,6724,6509],{},[59,6726,6512],{},[59,6728,6515],{},[59,6730,6518],{},[28,6732,6734],{"id":6733},"maplibre-gl-js-search-box-plugin","MapLibre GL JS Search Box Plugin",[24,6736,6737],{},"Our MapLibre GL JS plugin builds off of our JavaScript SDK and this plugin makes it easy and straightforward to add an\nautocomplete search box to your maps with just a few lines of code, all while leveraging best practices (debouncing of\nrequests, caching of previous results, and navigating to the chosen result) for the autocomplete search API!",[24,6739,6740],{},"Now you can easily implement an address auto-fill form for your e-Commerce application, saving your customers time and\nheadaches on the backend due to bad input data.",[24,6742,6743],{},"You can also use autocomplete to find:",[56,6745,6746,6749,6752,6755],{},[59,6747,6748],{},"Points of interest such as major landmarks, airports, campuses, etc.",[59,6750,6751],{},"Administrative areas (e.g. neighborhoods, cities, states, countries, etc.)",[59,6753,6754],{},"Postal codes",[59,6756,6757],{},"And more...",[28,6759,3396],{"id":3395},[24,6761,6762],{},"Since these are the initial versions of each SDK and plugin, we are looking for feedback from the community on updates,\nfeatures, and improvements that we can incorporate into upcoming releases.",[28,6764,6527],{"id":6526},[24,6766,6767],{},"You can find the releases, and their source code, in the usual places:",[56,6769,6770,6783,6796,6808],{},[59,6771,6772,6773,6778,6779],{},"JavaScript SDK: ",[35,6774,6777],{"href":6775,"rel":6776,"target":40},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@stadiamaps\u002Fapi",[39],"npm"," |\n",[35,6780,2818],{"href":6781,"rel":6782,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-ts",[39],[59,6784,6785,6786,6791,6792],{},"Python SDK: ",[35,6787,6790],{"href":6788,"rel":6789,"target":40},"https:\u002F\u002Fpypi.org\u002Fproject\u002Fstadiamaps\u002F",[39],"PyPi"," | ",[35,6793,2818],{"href":6794,"rel":6795,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-py",[39],[59,6797,6798,6799,6778,6804],{},"Kotlin SDK: ",[35,6800,6803],{"href":6801,"rel":6802,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-kotlin\u002Fpackages\u002F1887775",[39],"GitHub Packages",[35,6805,2818],{"href":6806,"rel":6807,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-kotlin",[39],[59,6809,6810,6811,6778,6814],{},"MapLibre GL JS Plugin: ",[35,6812,6777],{"href":6495,"rel":6813,"target":40},[39],[35,6815,2818],{"href":6816,"rel":6817,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fmaplibre-search-box",[39],[28,6819,1711],{"id":1710},[56,6821,6822,6827,6833],{},[59,6823,6541,6824,6545],{},[35,6825,1159],{"href":1482,"rel":6826,"target":40},[39],[59,6828,6829,6249],{},[35,6830,1720],{"href":6831,"rel":6832,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=sdk_launch&utm_content=maplibre_plugin_announcement",[39],[59,6834,1231,6835,1056,6838,3448,6841,352,6844,1749,6847,1753,6850,3461],{},[35,6836,1239],{"href":1237,"rel":6837,"target":40},[39],[35,6839,849],{"href":847,"rel":6840,"target":40},[39],[35,6842,1248],{"href":1246,"rel":6843,"target":40},[39],[35,6845,1253],{"href":1251,"rel":6846,"target":40},[39],[35,6848,1264],{"href":1262,"rel":6849,"target":40},[39],[35,6851,1270],{"href":1268,"rel":6852,"target":40},[39],{"title":168,"searchDepth":169,"depth":169,"links":6854},[6855,6856,6857,6858,6859,6860],{"id":6459,"depth":172,"text":6460},{"id":6500,"depth":172,"text":6501},{"id":6733,"depth":172,"text":6734},{"id":3395,"depth":172,"text":3396},{"id":6526,"depth":172,"text":6527},{"id":1710,"depth":172,"text":1711},"New JavaScript, Python, and Kotlin SDKs, along with a MapLibre GL JS Search Plugin, are now available.",[4095,6863,4090,4083,2746,6864],"JavaScript","Search Plugin",{},"\u002Fblog\u002Fnew-sdks-and-maplibre-plugin","2023-07-04","---\ndescription: \"New JavaScript, Python, and Kotlin SDKs, along with a MapLibre GL JS Search Plugin, are now available.\"\npublished: \"2023-07-04\"\nkeywords:\n  - SDK\n  - JavaScript\n  - Python\n  - Kotlin\n  - MapLibre\n  - Search Plugin\n---\n\n# Three New SDKs and MapLibre GL JS Search Plugin Are Now Available\n\nToday we are excited to announce the initial release of three SDKs ([JavaScript\u002FTypeScript](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fjavascript-typescript\u002F),\n[Python](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fpython\u002F), and [Kotlin](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fkotlin-jvm\u002F)), along\nwith a [MapLibre GL JS search box plugin](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@stadiamaps\u002Fmaplibre-search-box) for Stadia\nMaps services.\n\n## We've Listened and Delivered\n\nThese four projects round out our support for a large portion of our existing user base, including all browser-based\napps and many popular backend use cases too.\n\n## Why Use the SDKs?\n\nOf course you could write your code to directly interface with our APIs, but there are several benefits to taking\nadvantage of our SDKs:\n\n* Save time; no need to write your own API code since you have access to the full range of Stadia Maps geospatial APIs\n* Easily install via your favorite package manager\n* Faster access to documentation in your IDE with autocomplete\n* Always utilize the latest features because when we release a new API, we'll release an updated SDK\n\n## MapLibre GL JS Search Box Plugin\n\nOur MapLibre GL JS plugin builds off of our JavaScript SDK and this plugin makes it easy and straightforward to add an\nautocomplete search box to your maps with just a few lines of code, all while leveraging best practices (debouncing of\nrequests, caching of previous results, and navigating to the chosen result) for the autocomplete search API!\n\nNow you can easily implement an address auto-fill form for your e-Commerce application, saving your customers time and\nheadaches on the backend due to bad input data.\n\nYou can also use autocomplete to find:\n\n* Points of interest such as major landmarks, airports, campuses, etc.\n* Administrative areas (e.g. neighborhoods, cities, states, countries, etc.)\n* Postal codes\n* And more...\n\n## We Want Your Feedback\n\nSince these are the initial versions of each SDK and plugin, we are looking for feedback from the community on updates,\nfeatures, and improvements that we can incorporate into upcoming releases.\n\n## Where to Find\n\nYou can find the releases, and their source code, in the usual places:\n\n* JavaScript SDK: [npm](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@stadiamaps\u002Fapi) |\n[GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-ts)\n* Python SDK: [PyPi](https:\u002F\u002Fpypi.org\u002Fproject\u002Fstadiamaps\u002F) | [GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-py)\n* Kotlin SDK: [GitHub Packages](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-kotlin\u002Fpackages\u002F1887775) |\n[GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fstadiamaps-api-kotlin)\n* MapLibre GL JS Plugin: [npm](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@stadiamaps\u002Fmaplibre-search-box) |\n[GitHub](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fmaplibre-search-box)\n\n## Learn More & Next Steps\n\n- Read documentation about our [SDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F) and Plugins on our docs site.\n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=sdk_launch&utm_content=maplibre_plugin_announcement) to start building today!\n- Join our community on [Slack](https:\u002F\u002Fslack.openstreetmap.us\u002F) or [Discord](https:\u002F\u002Fdiscord.gg\u002FqRBy6qqtdT), follow us\non [Mastodon](https:\u002F\u002Fen.osm.town\u002F@stadiamaps), [Twitter](https:\u002F\u002Ftwitter.com\u002F@stadiamaps), or\n[LinkedIn](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fstadia-maps\u002F), or sign-up for our [mailing list](https:\u002F\u002Feepurl.com\u002Fgs51fD)!",{"title":6689,"description":6861},"blog\u002Fnew-sdks-and-maplibre-plugin","j9zyrUxAxpaPhuKkQNZl6oBP264LC7IkuopuVtOaOAc",{"id":6873,"title":6874,"abstract":7,"author":7,"body":6875,"description":6997,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":6998,"meta":7000,"modified":7,"navigation":187,"path":7001,"proficiencyLevel":7,"published":7002,"rawbody":7003,"schemaOrg":7,"schemaType":7,"seo":7004,"stem":7005,"__hash__":7006},"blog\u002Fblog\u002Fgeocoding-and-autocomplete-search-generally-available.md","Generally Available: Geocoding & Autocomplete Search with SDKs",{"type":14,"value":6876,"toc":6990},[6877,6880,6883,6886,6895,6899,6905,6908,6911,6914,6919,6922,6930,6933,6946,6949,6951,6954,6957,6959],[17,6878,6874],{"id":6879},"generally-available-geocoding-autocomplete-search-with-sdks",[24,6881,6882],{},"We are excited to announce the immediate general availability of Stadia Maps Geocoding & Autocomplete Search APIs, the\nnext step as we build the Alternative Location Platform. With these APIs, developers can create all-new user\nexperiences critical for many products. Starting today, it is easier to solve key back-office problems such as finding\nthe geographic location of an address, converting between natural-language input and geographic coordinates, and adding\nautocomplete search for even better and more immersive map experiences. As with all our APIs, these solutions combine\nthe power of open data and open-source software and run on the same infrastructure platform as our existing reliable,\naffordable, and private location services.",[24,6884,6885],{},"To create the best available library of global places, we combined multiple open data sets, including OpenStreetMap,\nOpenAddresses, and more into one coherent API. Developers can rely on flexible filtering options to limit searches by\ncountry, bounding box, and more. When integrating, the rich API responses provide all the required data, with no extra\nwork.",[24,6887,6888,6889,6894],{},"Continuing our tradition of building on open source, we started by building on the excellent work of\nthe ",[35,6890,6893],{"href":6891,"rel":6892,"target":40},"https:\u002F\u002Fwww.pelias.io\u002F",[39],"Pelias"," project and its team. We then connected it with our existing services—with many\nmore integrations planned, and we added our own Stadia twist. We will contribute improvements and bug fixes back to\nPelias and other projects so that everyone can benefit.",[1205,6896,6898],{"id":6897},"forward-reverse-geocoding","Forward & Reverse Geocoding",[24,6900,6901,6902,458],{},"Developers around the world use forward and reverse geocoding to help users and computers work with geospatial data.\nGeocoding provides conversion between places described by natural language, such as addresses, points of interest, or\ncity names, and geographic coordinates, such as ",[349,6903,6904],{},"35.6895, 139.69171",[24,6906,6907],{},"For the developer adventuring into the unknown, our address search is complemented by intelligent approximation. This\nallows for a high-probability result, even for addresses that aren’t on the map. Using this, last-mile delivery and\nother services are able to ensure deliver of a package to even the newest apartment building.",[24,6909,6910],{},"If your data is already structured, such as input from an address form, the Structured Geocoding API provides the same\ngeocoding capabilities as the standard endpoint. This API enables easy lookups based on labeled fields such as\ncity, street, and country, and improves the quality of results when there are only a few inputs available.",[1205,6912,1507],{"id":6913},"autocomplete-search",[24,6915,6916],{},[1810,6917],{"alt":2646,"src":6918},"\u002Fimages\u002Fcontent\u002Fautocomplete-search-example.gif",[24,6920,6921],{},"Developers and users are familiar with the ubiquitous autocomplete search box on maps. By\nadding support for search-as-you-type functionality, Stadia Maps enables a range of user experiences. These include\nautofilling address forms for e-commerce and creating interactive map integrations that make it easy for users to find\nplaces anywhere in the world.",[24,6923,6924,6925,6929],{},"Our users have long requested search functionality for direct integration into maps. Using our new APIs and\n",[35,6926,6928],{"href":6495,"rel":6927,"target":40},[39],"integration for MapLibre GL JS",", developers can quickly\nbuild a map with a search box for any platform.",[1205,6931,1159],{"id":6932},"sdks",[24,6934,6935,6936,6940,6941,6945],{},"To make it easier for everyone to integrate these new APIs, we've developed SDKs. Today, we're launching the\n",[35,6937,6939],{"href":6470,"rel":6938,"target":40},[39],"TypeScript (JavaScript) SDK"," and\nthe ",[35,6942,6944],{"href":6483,"rel":6943,"target":40},[39],"Python SDK",", which support geocoding, routing, and a few other APIs.\nWe plan to add Kotlin and more in the near future.",[24,6947,6948],{},"Want to see a SDK in your favorite language? Drop us a line to help us prioritize which SDKs to build next!",[1205,6950,3184],{"id":4001},[24,6952,6953],{},"In alignment with our mission of making maps affordable and transparent, we have set competitive prices for our new\nGeocoding & Autocomplete Search APIs. Each request uses 30 credits, with precise costs depending on the plan you select\nand your specific usage.",[24,6955,6956],{},"Autocomplete Search is available on all plans—including our Free plan! However, Geocoding endpoints (forward, reverse,\nand structured) require a paid plan. Additionally, storing geocoding results for future use requires a Standard plan\nor above.",[1205,6958,1711],{"id":1710},[56,6960,6961,6967,6977,6984],{},[59,6962,6963,6964,458],{},"Find pricing details on our ",[35,6965,6966],{"href":148},"pricing page",[59,6968,6969,6970,2686,6973,6976],{},"Read documentation about ",[35,6971,798],{"href":6604,"rel":6972,"target":40},[39],[35,6974,1159],{"href":1482,"rel":6975,"target":40},[39]," on our docs site.",[59,6978,6979,6983],{},[35,6980,6982],{"href":6981},"mailto:support@stadiamaps.com?subject=Tell%20Me%20More%20About%20Geocoding","Schedule a call"," to learn more.",[59,6985,6986,6249],{},[35,6987,1720],{"href":6988,"rel":6989,"target":40},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_launch&utm_content=geocoding_ga_announcement",[39],{"title":168,"searchDepth":169,"depth":169,"links":6991},[6992,6993,6994,6995,6996],{"id":6897,"depth":669,"text":6898},{"id":6913,"depth":669,"text":1507},{"id":6932,"depth":669,"text":1159},{"id":4001,"depth":669,"text":3184},{"id":1710,"depth":669,"text":1711},"Build modern mapping experiences with autocomplete search and efficient operations with flexible geocoding APIs.",[402,1507,6999,4095],"Product Launch",{},"\u002Fblog\u002Fgeocoding-and-autocomplete-search-generally-available","2023-06-15","---\ndescription: \"Build modern mapping experiences with autocomplete search and efficient operations with flexible geocoding APIs.\"\npublished: \"2023-06-15\"\nkeywords:\n  - Geocoding\n  - Autocomplete Search\n  - Product Launch\n  - SDK\n---\n\n# Generally Available: Geocoding & Autocomplete Search with SDKs\n\nWe are excited to announce the immediate general availability of Stadia Maps Geocoding & Autocomplete Search APIs, the\nnext step as we build the Alternative Location Platform. With these APIs, developers can create all-new user\nexperiences critical for many products. Starting today, it is easier to solve key back-office problems such as finding\nthe geographic location of an address, converting between natural-language input and geographic coordinates, and adding\nautocomplete search for even better and more immersive map experiences. As with all our APIs, these solutions combine\nthe power of open data and open-source software and run on the same infrastructure platform as our existing reliable,\naffordable, and private location services.\n\nTo create the best available library of global places, we combined multiple open data sets, including OpenStreetMap,\nOpenAddresses, and more into one coherent API. Developers can rely on flexible filtering options to limit searches by\ncountry, bounding box, and more. When integrating, the rich API responses provide all the required data, with no extra\nwork.\n\nContinuing our tradition of building on open source, we started by building on the excellent work of\nthe [Pelias](https:\u002F\u002Fwww.pelias.io\u002F) project and its team. We then connected it with our existing services—with many\nmore integrations planned, and we added our own Stadia twist. We will contribute improvements and bug fixes back to\nPelias and other projects so that everyone can benefit.\n\n### Forward & Reverse Geocoding\n\nDevelopers around the world use forward and reverse geocoding to help users and computers work with geospatial data.\nGeocoding provides conversion between places described by natural language, such as addresses, points of interest, or\ncity names, and geographic coordinates, such as `35.6895, 139.69171`.\n\nFor the developer adventuring into the unknown, our address search is complemented by intelligent approximation. This\nallows for a high-probability result, even for addresses that aren’t on the map. Using this, last-mile delivery and\nother services are able to ensure deliver of a package to even the newest apartment building.\n\nIf your data is already structured, such as input from an address form, the Structured Geocoding API provides the same\ngeocoding capabilities as the standard endpoint. This API enables easy lookups based on labeled fields such as\ncity, street, and country, and improves the quality of results when there are only a few inputs available.\n\n### Autocomplete Search\n\n![Autocomplete Search Example](\u002Fimages\u002Fcontent\u002Fautocomplete-search-example.gif){}\n\nDevelopers and users are familiar with the ubiquitous autocomplete search box on maps. By\nadding support for search-as-you-type functionality, Stadia Maps enables a range of user experiences. These include\nautofilling address forms for e-commerce and creating interactive map integrations that make it easy for users to find\nplaces anywhere in the world.\n\nOur users have long requested search functionality for direct integration into maps. Using our new APIs and\n[integration for MapLibre GL JS](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@stadiamaps\u002Fmaplibre-search-box), developers can quickly\nbuild a map with a search box for any platform.\n\n### SDKs\n\nTo make it easier for everyone to integrate these new APIs, we've developed SDKs. Today, we're launching the\n[TypeScript (JavaScript) SDK](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fjavascript-typescript\u002F) and\nthe [Python SDK](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Fpython\u002F), which support geocoding, routing, and a few other APIs.\nWe plan to add Kotlin and more in the near future.\n\nWant to see a SDK in your favorite language? Drop us a line to help us prioritize which SDKs to build next!\n\n### Pricing\n\nIn alignment with our mission of making maps affordable and transparent, we have set competitive prices for our new\nGeocoding & Autocomplete Search APIs. Each request uses 30 credits, with precise costs depending on the plan you select\nand your specific usage.\n\nAutocomplete Search is available on all plans—including our Free plan! However, Geocoding endpoints (forward, reverse,\nand structured) require a paid plan. Additionally, storing geocoding results for future use requires a Standard plan\nor above.\n\n### Learn More & Next Steps\n\n- Find pricing details on our [pricing page](\u002Fpricing\u002F). \n- Read documentation about [geocoding](https:\u002F\u002Fdocs.stadiamaps.com\u002Fgeocoding-search-autocomplete\u002Foverview\u002F) and [SDKs](https:\u002F\u002Fdocs.stadiamaps.com\u002Fsdks\u002Foverview\u002F) on our docs site. \n- [Schedule a call](mailto:support@stadiamaps.com?subject=Tell%20Me%20More%20About%20Geocoding) to learn more. \n- [Create an account](https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_source=marketing_site&utm_medium=blog&utm_campaign=geocoding_launch&utm_content=geocoding_ga_announcement) to start building today!",{"title":6874,"description":6997},"blog\u002Fgeocoding-and-autocomplete-search-generally-available","tgxTy_ZVpoN6SYd284lRtiVou44JbWgeHKtNwoQqRaw",{"id":7008,"title":7009,"abstract":7,"author":7,"body":7010,"description":7043,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7044,"meta":7049,"modified":7,"navigation":187,"path":7050,"proficiencyLevel":7,"published":7051,"rawbody":7052,"schemaOrg":7,"schemaType":7,"seo":7053,"stem":7054,"__hash__":7055},"blog\u002Fblog\u002Feu-only-endpoints-are-now-available.md","European Union-only Endpoints Are Now Available",{"type":14,"value":7011,"toc":7041},[7012,7015,7018,7021,7030,7033],[17,7013,7009],{"id":7014},"european-union-only-endpoints-are-now-available",[24,7016,7017],{},"At Stadia Maps, privacy is our utmost priority.  That's why we develop all of our services with privacy as the\nfoundation.",[24,7019,7020],{},"While we are confident that our privacy practices and procedures satisfy General Data Protection Regulation (GDPR)\nrequirements by default, we now give you an option to route all requests to a server inside the European Union.\nThis helps customers who have wanted to guarantee their user requests and personally identifiable information (PII)\nremain within the European Union.",[24,7022,7023,7024,7029],{},"To accomplish this, we now offer ",[35,7025,7028],{"href":7026,"rel":7027,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Feu-gdpr-endpoints\u002F",[39],"EU-only endpoints",", enabling users\na way to exclusively connect to our EU-based servers.",[24,7031,7032],{},"We are happy to continue to make our commitment to privacy and GDPR compliance even more accessible.",[24,7034,7035,7036,458],{},"The EU-only endpoints are accessible on all ",[35,7037,7040],{"href":7038,"rel":7039,"target":40},"https:\u002F\u002Fstadiamaps.com\u002Fpricing\u002F",[39],"plans",{"title":168,"searchDepth":169,"depth":169,"links":7042},[],"Stadia Maps now offers European Union-only endpoints, ensuring users' requests never leave the EU.",[7045,7046,7047,7048],"EU Endpoints","Privacy","GDPR","Data Residency",{},"\u002Fblog\u002Feu-only-endpoints-are-now-available","2023-06-13","---\ndescription: Stadia Maps now offers European Union-only endpoints, ensuring users' requests never leave the EU.\npublished: 2023-06-13\nkeywords:\n  - EU Endpoints\n  - Privacy\n  - GDPR\n  - Data Residency\n---\n\n# European Union-only Endpoints Are Now Available\n\nAt Stadia Maps, privacy is our utmost priority.  That's why we develop all of our services with privacy as the\nfoundation.\n\nWhile we are confident that our privacy practices and procedures satisfy General Data Protection Regulation (GDPR)\nrequirements by default, we now give you an option to route all requests to a server inside the European Union.\nThis helps customers who have wanted to guarantee their user requests and personally identifiable information (PII)\nremain within the European Union.\n\nTo accomplish this, we now offer [EU-only endpoints](https:\u002F\u002Fdocs.stadiamaps.com\u002Feu-gdpr-endpoints\u002F), enabling users\na way to exclusively connect to our EU-based servers.\n\nWe are happy to continue to make our commitment to privacy and GDPR compliance even more accessible.\n\nThe EU-only endpoints are accessible on all [plans](https:\u002F\u002Fstadiamaps.com\u002Fpricing\u002F).",{"title":7009,"description":7043},"blog\u002Feu-only-endpoints-are-now-available","sGcnLi-xgcyKwp77a0sCTpBdfEDByCEhZyu2PFdOVDc",{"id":7057,"title":7058,"abstract":7,"author":7,"body":7059,"description":7116,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7117,"meta":7121,"modified":7,"navigation":187,"path":7122,"proficiencyLevel":7,"published":7123,"rawbody":7124,"schemaOrg":7,"schemaType":7,"seo":7125,"stem":7126,"__hash__":7127},"blog\u002Fblog\u002Fsatellite-maps-are-now-available.md","Satellite Maps Are Now Available",{"type":14,"value":7060,"toc":7112},[7061,7064,7076,7080,7082,7085,7088,7092,7099,7102,7109],[17,7062,7058],{"id":7063},"satellite-maps-are-now-available",[24,7065,7066,7067,7071,7072,7075],{},"The wait is over! We’re happy to announce the general availability of\nour ",[35,7068,7070],{"href":7069},"\u002Fproducts\u002Fmaps\u002Fmap-styles\u002Fsatellite-imagery\u002F","satellite maps",". The new maps are now available to all subscribers of our\n",[35,7073,7074],{"href":148},"revamped Standard and Professional plans",", which we announced last week.",[28,7077,7079],{"id":7078},"demo","Demo",[215,7081],{":center":1544,":scroll-zoom":218,":zoom":1545,"id":221,"theme":223},[24,7083,7084],{},"Go ahead and explore the map a bit before you keep reading. We'll wait! (Make sure to check out full-screen mode.)",[24,7086,7087],{},"If you're designing a real estate platform, planning a city, or building an app for the great outdoors, you need to know\nthe lay of the land. Your customers deserve the best, which is why we’ve partnered with industry leaders to source\nhigh-quality imagery that’s typically less than a year old. Our Alidade Satellite style pairs this with a\nminimalist approach to additional layers to give your data the context it needs.",[28,7089,7091],{"id":7090},"get-access-today","Get Access Today",[24,7093,3830,7094,7098],{},[35,7095,165],{"href":7096,"rel":7097,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fthemes#alidade-satellite",[39]," with everything you need\nto use the Alidade Satellite style. If you’re already using MapLibre GL or Leaflet, integration is only a few\nlines of code. And if you’re just getting started, our guides and tutorials will give you a jump start.",[24,7100,7101],{},"Sign up for the new Standard or Professional plan, and turn the earth into your canvas today.",[7103,7104,7106],"stadia-button",{"to":7105},"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_content=satellite_news_announcement&utm_source=marketing_site",[24,7107,7108],{},"Get started with satellite maps!",[852,7110,7111],{},"\n#map {\n  height: 600px;\n  width: auto;\n  margin-bottom: 20px;\n}\n",{"title":168,"searchDepth":169,"depth":169,"links":7113},[7114,7115],{"id":7078,"depth":172,"text":7079},{"id":7090,"depth":172,"text":7091},"The wait is over! Our satellite basemaps are now available. Turn the earth into your canvas today.",[7118,7119,7120,6999],"Satellite Maps","Aerial Imagery","Basemaps",{},"\u002Fblog\u002Fsatellite-maps-are-now-available","2023-01-25","---\ndescription: The wait is over! Our satellite basemaps are now available. Turn the earth into your canvas today.\npublished: 2023-01-25\nkeywords:\n  - Satellite Maps\n  - Aerial Imagery\n  - Basemaps\n  - Product Launch\n---\n\n# Satellite Maps Are Now Available\n\nThe wait is over! We&rsquo;re happy to announce the general availability of\nour [satellite maps](\u002Fproducts\u002Fmaps\u002Fmap-styles\u002Fsatellite-imagery\u002F). The new maps are now available to all subscribers of our\n[revamped Standard and Professional plans](\u002Fpricing\u002F), which we announced last week.\n\n## Demo\n\n::cross-platform-map{id=\"map\"}\n---\ncenter: [172, -43.2]\nscroll-zoom: true\nzoom: 7\ntheme: alidade_satellite\n---\n::\n\nGo ahead and explore the map a bit before you keep reading. We'll wait! (Make sure to check out full-screen mode.)\n\nIf you're designing a real estate platform, planning a city, or building an app for the great outdoors, you need to know\nthe lay of the land. Your customers deserve the best, which is why we&rsquo;ve partnered with industry leaders to source\nhigh-quality imagery that&rsquo;s typically less than a year old. Our Alidade Satellite style pairs this with a\nminimalist approach to additional layers to give your data the context it needs.\n\n## Get Access Today\n\nWe&rsquo;ve updated our [documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fthemes#alidade-satellite) with everything you need\nto use the Alidade Satellite style. If you&rsquo;re already using MapLibre GL or Leaflet, integration is only a few\nlines of code. And if you&rsquo;re just getting started, our guides and tutorials will give you a jump start.\n\nSign up for the new Standard or Professional plan, and turn the earth into your canvas today.\n\n::stadia-button{to=\"https:\u002F\u002Fclient.stadiamaps.com\u002Fsignup\u002F?utm_content=satellite_news_announcement&utm_source=marketing_site\"}\nGet started with satellite maps!\n::\n\n\u003Cstyle>\n#map {\n  height: 600px;\n  width: auto;\n  margin-bottom: 20px;\n}\n\u003C\u002Fstyle>\n",{"title":7058,"description":7116},"blog\u002Fsatellite-maps-are-now-available","G4vsq3pCT7zC-8JT4iBfE7LkStLM4Ji2mo8qvABruXg",{"id":7129,"title":7130,"abstract":7,"author":7,"body":7131,"description":7180,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7181,"meta":7184,"modified":7,"navigation":187,"path":7185,"proficiencyLevel":7,"published":7186,"rawbody":7187,"schemaOrg":7,"schemaType":7,"seo":7188,"stem":7189,"__hash__":7190},"blog\u002Fblog\u002Fplan-updates-2023.md","New Plans & Pricing in 2023",{"type":14,"value":7132,"toc":7174},[7133,7136,7140,7143,7147,7150,7153,7159,7163,7166,7169],[17,7134,7130],{"id":7135},"new-plans-pricing-in-2023",[28,7137,7139],{"id":7138},"whats-changing","What’s Changing",[24,7141,7142],{},"Effective today, we are updating our pricing policies and plans. We have identified some ways our current\npricing causes confusion, and we are updating how accounts are granted access to features.",[1205,7144,7146],{"id":7145},"change-1-account-usage","Change #1: Account Usage",[24,7148,7149],{},"The biggest change is how account usage is calculated. First, plans will now have a monthly usage limit instead\nof a daily usage limit. Second, we are replacing \"map views\" and \"API requests\" with a single, simplified credit\nsystem.",[24,7151,7152],{},"Each plan will come with an included amount of credits for each month, and each request you make to our APIs\nwill use a set number of credits (e.g., a raster map tile will count as 1 credit, a static map as 10 credits,\nand a route request as 10 credits).",[24,7154,7155,7156,7158],{},"For ",[611,7157,4684],{}," paid plans, we will allow users to choose between the option to be hard limited (i.e.,\nadditional requests will be blocked) when the included credits are consumed or accruing additional usage fees.\nFree plans will continue being hard limited when the usage limit is reached.",[1205,7160,7162],{"id":7161},"change-2-available-features","Change #2: Available Features",[24,7164,7165],{},"Going forward, each plan will be granted access to a set of APIs. More advanced plans will have access to more\nfeatures; less advanced plans will have access to fewer features. For example, you will now need the Starter\nplan to gain access to our Static Maps API or the Standard plan for the new Satellite Basemap.",[24,7167,7168],{},"Legacy plans will retain their existing feature set as of January 11th, but will need to upgrade to access new\nfeatures (ex: satellite basemaps). If you were a subscriber as of January 11th, we have emailed you with a\nlimited time upgrade offer to get a substantial discount on any of the new plans.",[24,7170,7171,7172],{},"You can see all the details about our new pricing on our updated ",[35,7173,6966],{"href":148},{"title":168,"searchDepth":169,"depth":169,"links":7175},[7176],{"id":7138,"depth":172,"text":7139,"children":7177},[7178,7179],{"id":7145,"depth":669,"text":7146},{"id":7161,"depth":669,"text":7162},"Announcement: We've released new plans and pricing.",[3184,7182,3183,7183],"Plans","Billing",{},"\u002Fblog\u002Fplan-updates-2023","2023-01-12","---\ndescription: \"Announcement: We've released new plans and pricing.\"\npublished: 2023-01-12\nkeywords:\n  - Pricing\n  - Plans\n  - Credits\n  - Billing\n---\n\n# New Plans & Pricing in 2023\n\n## What&rsquo;s Changing\n\nEffective today, we are updating our pricing policies and plans. We have identified some ways our current\npricing causes confusion, and we are updating how accounts are granted access to features.\n\n### Change #1: Account Usage\n\nThe biggest change is how account usage is calculated. First, plans will now have a monthly usage limit instead\nof a daily usage limit. Second, we are replacing \"map views\" and \"API requests\" with a single, simplified credit\nsystem.\n\nEach plan will come with an included amount of credits for each month, and each request you make to our APIs\nwill use a set number of credits (e.g., a raster map tile will count as 1 credit, a static map as 10 credits,\nand a route request as 10 credits).\n\nFor *new* paid plans, we will allow users to choose between the option to be hard limited (i.e.,\nadditional requests will be blocked) when the included credits are consumed or accruing additional usage fees.\nFree plans will continue being hard limited when the usage limit is reached.\n\n### Change #2: Available Features\n\nGoing forward, each plan will be granted access to a set of APIs. More advanced plans will have access to more\nfeatures; less advanced plans will have access to fewer features. For example, you will now need the Starter\nplan to gain access to our Static Maps API or the Standard plan for the new Satellite Basemap.\n\nLegacy plans will retain their existing feature set as of January 11th, but will need to upgrade to access new\nfeatures (ex: satellite basemaps). If you were a subscriber as of January 11th, we have emailed you with a\nlimited time upgrade offer to get a substantial discount on any of the new plans.\n\nYou can see all the details about our new pricing on our updated [pricing page](\u002Fpricing\u002F)",{"title":7130,"description":7180},"blog\u002Fplan-updates-2023","SfdfTTa-BJYkr1XEJvD8yiLO1des7SdNdTEsI_5BRYQ",{"id":7192,"title":7193,"abstract":7,"author":7,"body":7194,"description":7265,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7266,"meta":7268,"modified":7,"navigation":187,"path":7269,"proficiencyLevel":7,"published":7270,"rawbody":7271,"schemaOrg":7,"schemaType":7,"seo":7272,"stem":7273,"__hash__":7274},"blog\u002Fblog\u002Fmap-style-improvements-highway-shields-and-house-numbers.md","Map Style Improvements and House Number Layer",{"type":14,"value":7195,"toc":7259},[7196,7199,7202,7206,7211,7221,7225,7229,7232,7236,7240,7243,7247,7251],[17,7197,7193],{"id":7198},"map-style-improvements-and-house-number-layer",[24,7200,7201],{},"Today, we’re announcing a significant set of improvements to our map data and styles. For our Alidade family of\nstyles, it's the most significant since we launched five years ago!",[28,7203,7205],{"id":7204},"low-zoom-improvements","Low Zoom Improvements",[7207,7208],"content-twenty-twenty",{"afterSrc":7209,"beforeSrc":7210},"\u002Fassets\u002F2022-new-z0.png","\u002Fassets\u002F2022-old-z0.png",[24,7212,7213,7214,2686,7218,458],{},"By reducing label crowding at z0, improving the display of oceans in several styles, and fixing cut labels, we have\ndramatically improved the quality of our lower zoom levels. These improvements and fixes are most noticeable for users\nof our raster ",[35,7215,7217],{"href":7216},"\u002Fproducts\u002Fmaps\u002Finteractive-basemaps\u002F","map tiles",[35,7219,7220],{"href":581},"static maps",[28,7222,7224],{"id":7223},"improved-legibility","Improved Legibility",[7207,7226],{"afterSrc":7227,"beforeSrc":7228},"\u002Fassets\u002F2022-new-countries.png","\u002Fassets\u002F2022-old-countries.png",[24,7230,7231],{},"We have differentiated a number of features better in this style update to improve legibility. The most obvious change\nis with country names, which are now much easier to pick out due to more distinctive typography. We’ve similarly\nimproved the legibility of water, state, and neighborhood labels in our Alidade Smooth and Outdoors styles.",[28,7233,7235],{"id":7234},"highway-shields","Highway Shields",[7207,7237],{"afterSrc":7238,"beforeSrc":7239},"\u002Fassets\u002F2022-new-highways.png","\u002Fassets\u002F2022-old-highways.png",[24,7241,7242],{},"Minimalism has always been a guiding design principle for our Alidade Smooth family of styles. As a result, every\naddition should enhance legibility while keeping your data front and center. Highway shields pass this test with flying\ncolors and will provide valuable context for any data set. We currently offer several styles of shields within the US\nbased on the highway type (e.g., different shields for interstates and state route). Shields for US state routes and\nnational highway networks outside the US are planned for future updates.",[28,7244,7246],{"id":7245},"house-numbers","House Numbers",[7207,7248],{"afterSrc":7249,"beforeSrc":7250},"\u002Fassets\u002F2022-new-nycz14.png","\u002Fassets\u002F2022-old-nycz14.png",[24,7252,7253,7254,458],{},"You asked; we listened! Our vector tiles at z14 now include a house number layer, and you can see it in action on our\nOSM Bright style. If you would like to add house numbers to another style, check out our\nrevamped ",[35,7255,7258],{"href":7256,"rel":7257,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fcustom-styles\u002F",[39],"tutorial",{"title":168,"searchDepth":169,"depth":169,"links":7260},[7261,7262,7263,7264],{"id":7204,"depth":172,"text":7205},{"id":7223,"depth":172,"text":7224},{"id":7234,"depth":172,"text":7235},{"id":7245,"depth":172,"text":7246},"Improved Alidade Smooth and Outdoors map styles, and added house numbers.",[6427,7267,7246,7235,6428],"Alidade",{},"\u002Fblog\u002Fmap-style-improvements-highway-shields-and-house-numbers","2022-12-16","---\ndescription: Improved Alidade Smooth and Outdoors map styles, and added house numbers.\npublished: 2022-12-16\nkeywords:\n  - Map Styles\n  - Alidade\n  - House Numbers\n  - Highway Shields\n  - Cartography\n---\n\n# Map Style Improvements and House Number Layer\n\nToday, we&rsquo;re announcing a significant set of improvements to our map data and styles. For our Alidade family of\nstyles, it's the most significant since we launched five years ago!\n\n## Low Zoom Improvements\n\n::content-twenty-twenty\n---\nafterSrc: \"\u002Fassets\u002F2022-new-z0.png\"\nbeforeSrc: \"\u002Fassets\u002F2022-old-z0.png\"\n---\n::\n\nBy reducing label crowding at z0, improving the display of oceans in several styles, and fixing cut labels, we have\ndramatically improved the quality of our lower zoom levels. These improvements and fixes are most noticeable for users\nof our raster [map tiles](\u002Fproducts\u002Fmaps\u002Finteractive-basemaps\u002F) and [static maps](\u002Fproducts\u002Fmaps\u002Fstatic-maps\u002F).\n\n## Improved Legibility\n\n::content-twenty-twenty\n---\nafterSrc: \"\u002Fassets\u002F2022-new-countries.png\"\nbeforeSrc: \"\u002Fassets\u002F2022-old-countries.png\"\n---\n::\n\nWe have differentiated a number of features better in this style update to improve legibility. The most obvious change\nis with country names, which are now much easier to pick out due to more distinctive typography. We&rsquo;ve similarly\nimproved the legibility of water, state, and neighborhood labels in our Alidade Smooth and Outdoors styles.\n\n## Highway Shields\n\n::content-twenty-twenty\n---\nafterSrc: \"\u002Fassets\u002F2022-new-highways.png\"\nbeforeSrc: \"\u002Fassets\u002F2022-old-highways.png\"\n---\n::\n\nMinimalism has always been a guiding design principle for our Alidade Smooth family of styles. As a result, every\naddition should enhance legibility while keeping your data front and center. Highway shields pass this test with flying\ncolors and will provide valuable context for any data set. We currently offer several styles of shields within the US\nbased on the highway type (e.g., different shields for interstates and state route). Shields for US state routes and\nnational highway networks outside the US are planned for future updates.\n\n## House Numbers\n\n::content-twenty-twenty\n---\nafterSrc: \"\u002Fassets\u002F2022-new-nycz14.png\"\nbeforeSrc: \"\u002Fassets\u002F2022-old-nycz14.png\"\n---\n::\n\nYou asked; we listened! Our vector tiles at z14 now include a house number layer, and you can see it in action on our\nOSM Bright style. If you would like to add house numbers to another style, check out our\nrevamped [tutorial](https:\u002F\u002Fdocs.stadiamaps.com\u002Fcustom-styles\u002F).",{"title":7193,"description":7265},"blog\u002Fmap-style-improvements-highway-shields-and-house-numbers","WcdGj32y54KUpkl_3aMWI5jeoWT4WS9YNivTb_G1VAc",{"id":7276,"title":7277,"abstract":7,"author":7,"body":7278,"description":7308,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7309,"meta":7312,"modified":7,"navigation":187,"path":7313,"proficiencyLevel":7,"published":7314,"rawbody":7315,"schemaOrg":7,"schemaType":7,"seo":7316,"stem":7317,"__hash__":7318},"blog\u002Fblog\u002Fannouncing-simplified-account-level-billing.md","Announcing Simplified Account-Based Billing",{"type":14,"value":7279,"toc":7306},[7280,7283,7286,7293],[17,7281,7277],{"id":7282},"announcing-simplified-account-based-billing",[24,7284,7285],{},"At Stadia Maps, we're always trying to make maps more accessible. Since launching, we have required a subscription for\neach property in your Stadia Maps account. However, over time, we recognized this approach added unnecessary complexity\nand confusion (it is the top support question we receive). So starting today, we’re making your life easier by\nbilling per account rather than per property.",[24,7287,7288,7289,7292],{},"Properties are still a useful way that many of our customers track usage of individual applications, so they are not\ngoing away. In fact, you can still create as many of them as you like! The difference is that your account only needs a\nsingle subscription that covers the ",[611,7290,7291],{},"combined"," usage of all your properties. We’ve added an account-level\noverview to the client dashboard so that you can see the aggregate usage against your plan limit.\nIf you previously had multiple subscriptions, we’ve got you\ncovered! We have already canceled any extra subscriptions and\nemailed you with the good news.",[24,7294,7295,7296,7300,7301,7305],{},"Of course, our ",[35,7297,7299],{"href":7298},"\u002Fterms-of-service\u002F","terms of service"," still apply, and you will need multiple accounts to use maps\nacross multiple entities. See our ",[35,7302,7304],{"href":7303},"\u002Ffaqs\u002F","FAQ"," to learn more about shared billing, and when you need multiple accounts.",{"title":168,"searchDepth":169,"depth":169,"links":7307},[],"We've simplified billing by moving to a single subscription per account.",[7183,7310,7311],"Account Management","Subscription",{},"\u002Fblog\u002Fannouncing-simplified-account-level-billing","2022-12-05","---\ndescription: \"We've simplified billing by moving to a single subscription per account.\"\npublished: 2022-12-05\nkeywords:\n  - Billing\n  - Account Management\n  - Subscription\n---\n\n# Announcing Simplified Account-Based Billing\n\nAt Stadia Maps, we're always trying to make maps more accessible. Since launching, we have required a subscription for\neach property in your Stadia Maps account. However, over time, we recognized this approach added unnecessary complexity\nand confusion (it is the top support question we receive). So starting today, we&rsquo;re making your life easier by\nbilling per account rather than per property.\n\nProperties are still a useful way that many of our customers track usage of individual applications, so they are not\ngoing away. In fact, you can still create as many of them as you like! The difference is that your account only needs a\nsingle subscription that covers the _combined_ usage of all your properties. We&rsquo;ve added an account-level\noverview to the client dashboard so that you can see the aggregate usage against your plan limit.\nIf you previously had multiple subscriptions, we&rsquo;ve got you\ncovered! We have already canceled any extra subscriptions and\nemailed you with the good news.\n\nOf course, our [terms of service](\u002Fterms-of-service\u002F) still apply, and you will need multiple accounts to use maps\nacross multiple entities. See our [FAQ](\u002Ffaqs\u002F) to learn more about shared billing, and when you need multiple accounts.\n",{"title":7277,"description":7308},"blog\u002Fannouncing-simplified-account-level-billing","oaVKudPQLFtmC9JxTwnFN9_2koMy8mqR9dgSXikd0WA",{"id":7320,"title":7321,"abstract":7,"author":7,"body":7322,"description":7393,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7394,"meta":7396,"modified":7,"navigation":187,"path":7397,"proficiencyLevel":7,"published":7398,"rawbody":7399,"schemaOrg":7,"schemaType":7,"seo":7400,"stem":7401,"__hash__":7402},"blog\u002Fblog\u002Fstatic-maps-with-polylines.md","Announcing Improved Static Maps with Customizable Lines",{"type":14,"value":7323,"toc":7387},[7324,7327,7334,7338,7341,7347,7351,7354,7359,7362,7366,7374,7378,7384],[17,7325,7321],{"id":7326},"announcing-improved-static-maps-with-customizable-lines",[24,7328,7329,7330,7333],{},"We are excited to announce the release of our improved static maps product! ",[35,7331,7332],{"href":581},"Static maps"," enable\ndevelopers to quickly and easily include maps in their applications as images. Included in this release are many\nperformance improvements, the ability to directly draw lines on the map, and overhauled documentation.",[28,7335,7337],{"id":7336},"polyline-support-for-static-maps","Polyline Support for Static Maps",[24,7339,7340],{},"Since the static maps product launched, customers have requested\nthe ability to draw lines directly on static maps, and today, we\nare officially announcing support for rendering polylines. With our\nupdated API, developers can save time and resources by using static maps\nto solve problems where previously interactive maps or some other\npostprocessing was required.",[24,7342,7343],{},[1810,7344],{"alt":7345,"src":7346},"a map of markers and a line in Tallinn, Estonia","https:\u002F\u002Fstadiamaps.com\u002Fstatic\u002Falidade_smooth?center=59.438484,24.742595&zoom=13&l=oj_kpBkhmen@vFvDlStSdIzN%60BxCfMfShA%60B~@%7CAvCrDpG%60FfVfRb%5CzSrBdBhZx%5CpFdM~BpFn@zAxCrHrH%7CQjOh_@NtM%7CVv@d@aHdHEfD%5E%5CDhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG%5DcEc@%7BFm@uF%5DoDgAwJhAm@vMqGoAs%7B@dAMfG_@dE_@Ezb@ExWzBBZ?L@%7CDnTtAqE~CyMp@sB%7C@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA%7D@~CVbB%60@pDtAN%7DDxD%60AdFi@vBIxBIe@aMuAgPyFwy@%7BCa_@yFar@%5B%7BC_AsGuAkGqEgY_CmLqAuFuHi%5Bm@vBq@hC,333333,5&m=59.436884,24.742595&m=59.437485,24.743150&m=59.434931,24.745442&m=59.441293,24.747380&m=59.435561,24.747605&size=600x250@2x",[28,7348,7350],{"id":7349},"customizable-from-the-start","Customizable from the Start",[24,7352,7353],{},"Whether you need to visualize a navigation route, a hiking track, or your most recent flight path, adjusting the look\nand feel is key to a great static map. That’s why we made sure you can fully customize each line to achieve\nthe perfect match to your app, just as you can already do with markers.",[24,7355,7356],{},[1810,7357],{"alt":7345,"src":7358},"https:\u002F\u002Fstadiamaps.com\u002Fstatic\u002Falidade_smooth_dark?center=59.438484,24.742595&zoom=13&l=oj_kpBkhmen@vFvDlStSdIzN%60BxCfMfShA%60B~@%7CAvCrDpG%60FfVfRb%5CzSrBdBhZx%5CpFdM~BpFn@zAxCrHrH%7CQjOh_@NtM%7CVv@d@aHdHEfD%5E%5CDhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG%5DcEc@%7BFm@uF%5DoDgAwJhAm@vMqGoAs%7B@dAMfG_@dE_@Ezb@ExWzBBZ?L@%7CDnTtAqE~CyMp@sB%7C@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA%7D@~CVbB%60@pDtAN%7DDxD%60AdFi@vBIxBIe@aMuAgPyFwy@%7BCa_@yFar@%5B%7BC_AsGuAkGqEgY_CmLqAuFuHi%5Bm@vBq@hC,ffdd00,10&m=59.436884,24.742595&m=59.437485,24.743150&m=59.434931,24.745442&m=59.441293,24.747380&m=59.435561,24.747605&size=600x250@2x",[24,7360,7361],{},"With these updates, the static maps experience is faster, smoother, and more integrated than ever before.",[28,7363,7365],{"id":7364},"get-started-today","Get Started Today!",[24,7367,7368,7369,7373],{},"We've updated our ",[35,7370,3995],{"href":7371,"rel":7372,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fstatic-maps\u002F",[39]," so it's even easier\nto get started building maps. Update your current maps or create your first static map today!",[28,7375,7377],{"id":7376},"one-more-thing-a-new-pop-location-in-mumbai","One More Thing: A new PoP Location in Mumbai",[24,7379,7380],{},[1810,7381],{"alt":7382,"src":7383},"map of India with Mumbai highlighted","https:\u002F\u002Ftiles.stadiamaps.com\u002Fstatic\u002Fosm_bright?m=19.076111,72.8775&center=19.076111,72.8775&zoom=4&size=600x250@2x",[24,7385,7386],{},"As part of our efforts to support our global customer-base with high-reliability, low-latency, and unbeatable\nperformance, we’re always looking for ways to expand our PoP network. After some unexpected delays, we’re\nnow able to unveil a new PoP region in Mumbai, allowing us to better serve our Indian users. We will continue expanding\nthe network in coordination with our infrastructure partners. New locations in Australia and Canada are already planned.",{"title":168,"searchDepth":169,"depth":169,"links":7388},[7389,7390,7391,7392],{"id":7336,"depth":172,"text":7337},{"id":7349,"depth":172,"text":7350},{"id":7364,"depth":172,"text":7365},{"id":7376,"depth":172,"text":7377},"Improved Static Maps with Customizable Lines: Add polylines to static maps and improved performance in India",[3850,7395,3852,1289],"Polylines",{},"\u002Fblog\u002Fstatic-maps-with-polylines","2022-09-09","---\ndescription: \"Improved Static Maps with Customizable Lines: Add polylines to static maps and improved performance in India\"\npublished: 2022-09-09\nkeywords:\n  - Static Maps\n  - Polylines\n  - Map Images\n  - API Update\n---\n\n# Announcing Improved Static Maps with Customizable Lines\n\nWe are excited to announce the release of our improved static maps product! [Static maps](\u002Fproducts\u002Fmaps\u002Fstatic-maps\u002F) enable\ndevelopers to quickly and easily include maps in their applications as images. Included in this release are many\nperformance improvements, the ability to directly draw lines on the map, and overhauled documentation.\n\n## Polyline Support for Static Maps\n\nSince the static maps product launched, customers have requested\nthe ability to draw lines directly on static maps, and today, we\nare officially announcing support for rendering polylines. With our\nupdated API, developers can save time and resources by using static maps\nto solve problems where previously interactive maps or some other\npostprocessing was required.\n\n![a map of markers and a line in Tallinn, Estonia](https:\u002F\u002Fstadiamaps.com\u002Fstatic\u002Falidade_smooth?center=59.438484,24.742595&zoom=13&l=oj_kpBkhmen@vFvDlStSdIzN`BxCfMfShA`B~@|AvCrDpG`FfVfRb\\zSrBdBhZx\\pFdM~BpFn@zAxCrHrH|QjOh_@NtM|Vv@d@aHdHEfD^\\DhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG]cEc@{Fm@uF]oDgAwJhAm@vMqGoAs{@dAMfG_@dE_@Ezb@ExWzBBZ?L@|DnTtAqE~CyMp@sB|@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA}@~CVbB`@pDtAN}DxD`AdFi@vBIxBIe@aMuAgPyFwy@{Ca_@yFar@[{C_AsGuAkGqEgY_CmLqAuFuHi[m@vBq@hC,333333,5&m=59.436884,24.742595&m=59.437485,24.743150&m=59.434931,24.745442&m=59.441293,24.747380&m=59.435561,24.747605&size=600x250@2x)\n\n## Customizable from the Start\n\nWhether you need to visualize a navigation route, a hiking track, or your most recent flight path, adjusting the look\nand feel is key to a great static map. That&rsquo;s why we made sure you can fully customize each line to achieve\nthe perfect match to your app, just as you can already do with markers.\n\n![a map of markers and a line in Tallinn, Estonia](https:\u002F\u002Fstadiamaps.com\u002Fstatic\u002Falidade_smooth_dark?center=59.438484,24.742595&zoom=13&l=oj_kpBkhmen@vFvDlStSdIzN`BxCfMfShA`B~@|AvCrDpG`FfVfRb\\zSrBdBhZx\\pFdM~BpFn@zAxCrHrH|QjOh_@NtM|Vv@d@aHdHEfD^\\DhCh@nIjFlFvE~CfCzAzAdFjFt@t@~EdG]cEc@{Fm@uF]oDgAwJhAm@vMqGoAs{@dAMfG_@dE_@Ezb@ExWzBBZ?L@|DnTtAqE~CyMp@sB|@n@XUx@uBjAiApBi@lBp@hAtAzAClSjJzAkMtAl@dA}@~CVbB`@pDtAN}DxD`AdFi@vBIxBIe@aMuAgPyFwy@{Ca_@yFar@[{C_AsGuAkGqEgY_CmLqAuFuHi[m@vBq@hC,ffdd00,10&m=59.436884,24.742595&m=59.437485,24.743150&m=59.434931,24.745442&m=59.441293,24.747380&m=59.435561,24.747605&size=600x250@2x)\n\nWith these updates, the static maps experience is faster, smoother, and more integrated than ever before.\n\n## Get Started Today!\n\nWe've updated our [static maps documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Fstatic-maps\u002F) so it's even easier\nto get started building maps. Update your current maps or create your first static map today!\n\n## One More Thing: A new PoP Location in Mumbai\n\n![map of India with Mumbai highlighted](https:\u002F\u002Ftiles.stadiamaps.com\u002Fstatic\u002Fosm_bright?m=19.076111,72.8775&center=19.076111,72.8775&zoom=4&size=600x250@2x)\n\nAs part of our efforts to support our global customer-base with high-reliability, low-latency, and unbeatable\nperformance, we&rsquo;re always looking for ways to expand our PoP network. After some unexpected delays, we&rsquo;re\nnow able to unveil a new PoP region in Mumbai, allowing us to better serve our Indian users. We will continue expanding\nthe network in coordination with our infrastructure partners. New locations in Australia and Canada are already planned.",{"title":7321,"description":7393},"blog\u002Fstatic-maps-with-polylines","1FIL2S7ywVlQudz6Ouu4cfzpCELkZPFuniieuCeK3Ec",{"id":7404,"title":7405,"abstract":7,"author":7,"body":7406,"description":7514,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7515,"meta":7518,"modified":7,"navigation":187,"path":7519,"proficiencyLevel":7,"published":7520,"rawbody":7521,"schemaOrg":7,"schemaType":7,"seo":7522,"stem":7523,"__hash__":7524},"blog\u002Fblog\u002Fproduct-updates-time-zones-and-docs.md","Announcing Time Zone APIs and a Documentation Refresh",{"type":14,"value":7407,"toc":7507},[7408,7411,7417,7431,7435,7438,7446,7450,7456,7460,7484,7496,7500],[17,7409,7405],{"id":7410},"announcing-time-zone-apis-and-a-documentation-refresh",[24,7412,7413,7414,458],{},"We are excited to announce two important product updates today. Following a period of closed beta testing, we are\nofficially releasing our ",[35,7415,7416],{"href":632},"time zone API",[24,7418,7419,7420,7425,7426,458],{},"Along with this release, we’ve given our ",[35,7421,7424],{"href":7422,"rel":7423,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com",[39],"developer documentation","\nlong-overdue facelift and added an exhaustive ",[35,7427,7430],{"href":7428,"rel":7429,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fapi-reference\u002F",[39],"API reference",[28,7432,7434],{"id":7433},"time-zone-api","Time Zone API",[24,7436,7437],{},"Build time zone aware applications with our new Time Zone APIs! Whether you need to determine the local time\nzone of an event or plan a round-the-world trip, our new Time Zone APIs give\nyou the simple tools needed to make your app a little bit smarter.",[24,7439,7440,7441,7445],{},"Our newest API enhances your applications with time zone information for any point on earth. You supply the\ncoordinates, and we provide the time zone in a few useful formats, including the canonical time zone identifier\nand UTC offset information. In addition to the standard UTC offset, the time zone API provides any special\noffsets, such as if daylight saving or summer time is in effect. You can also specify an effective timestamp to\nretrieve the UTC offsets at a point in the past or future. Check out the\n",[35,7442,165],{"href":7443,"rel":7444,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Ftz\u002F",[39]," for the full details.",[1205,7447,7449],{"id":7448},"get-stated-with-the-time-zone-api","Get Stated with the Time Zone API",[24,7451,7452,7453,458],{},"We can’t wait to see what you build with our new Time Zone API. To get you started, we’ve written up a fresh\nPython tutorial in our ",[35,7454,165],{"href":7443,"rel":7455,"target":40},[39],[28,7457,7459],{"id":7458},"documentation-refresh","Documentation Refresh",[24,7461,7462,7463,7468,7469,7474,7475,7479,7480,7483],{},"Speaking of docs, we recently gave our ",[35,7464,7467],{"href":7465,"rel":7466,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002F",[39],"docs",".\na long-overdue facelift, in large part thanks to ",[35,7470,7473],{"href":7471,"rel":7472,"target":40},"https:\u002F\u002Fsquidfunk.github.io\u002Fmkdocs-material\u002F",[39],"Material for MkDocs","\n(which we now ",[35,7476,7478],{"href":7477,"target":40},"https:\u002F\u002Fgithub.com\u002Fsponsors\u002Fsquidfunk","sponsor","). This is a\n",[611,7481,7482],{},"massive"," upgrade which includes dark mode, better looking code blocks, improved navigation, and more.",[24,7485,7486,7487,7490,7491,7495],{},"We’ve also added a full ",[35,7488,7430],{"href":7428,"rel":7489,"target":40},[39]," that makes it easier to see\nall the endpoints we offer, along with comprehensive schema documentation. The new reference is generated from\nan ",[35,7492,7494],{"href":7493,"target":40},"https:\u002F\u002Fapi.stadiamaps.com\u002Fopenapi.yaml","OpenAPI specification",",\nwhich we will keep up to date as we add new endpoints. This machine-readable spec\ncan be used to generate an up-to-date API client in any major programming language, and allows us to provide you\nwith the new handy online API explorer.",[28,7497,7499],{"id":7498},"talk-to-us","Talk to us!",[24,7501,7502,7503,7506],{},"What else do you want to do with our APIs? We’re always happy to\nhear what else we can do for you or just learn about what\nyou’re working on! You can get in touch via\n",[35,7504,7505],{"href":3838},"email"," or the social links\nbelow.",{"title":168,"searchDepth":169,"depth":169,"links":7508},[7509,7512,7513],{"id":7433,"depth":172,"text":7434,"children":7510},[7511],{"id":7448,"depth":669,"text":7449},{"id":7458,"depth":172,"text":7459},{"id":7498,"depth":172,"text":7499},"Product Update: Time zone API release and a much-needed documentation overhaul.",[7434,7516,7517],"Documentation","Product Update",{},"\u002Fblog\u002Fproduct-updates-time-zones-and-docs","2022-07-28","---\npublished: 2022-07-28\ndescription: \"Product Update: Time zone API release and a much-needed documentation overhaul.\"\nkeywords:\n  - Time Zone API\n  - Documentation\n  - Product Update\n---\n\n# Announcing Time Zone APIs and a Documentation Refresh\n\nWe are excited to announce two important product updates today. Following a period of closed beta testing, we are\nofficially releasing our [time zone API](\u002Fproducts\u002Fgeospatial-apis\u002F).\n\nAlong with this release, we&rsquo;ve given our [developer documentation](https:\u002F\u002Fdocs.stadiamaps.com){target=\"_blank\"}\nlong-overdue facelift and added an exhaustive [API reference](https:\u002F\u002Fdocs.stadiamaps.com\u002Fapi-reference\u002F){target=\"_blank\"}.\n\n## Time Zone API\nBuild time zone aware applications with our new Time Zone APIs! Whether you need to determine the local time\nzone of an event or plan a round-the-world trip, our new Time Zone APIs give\nyou the simple tools needed to make your app a little bit smarter.\n\nOur newest API enhances your applications with time zone information for any point on earth. You supply the\ncoordinates, and we provide the time zone in a few useful formats, including the canonical time zone identifier\nand UTC offset information. In addition to the standard UTC offset, the time zone API provides any special\noffsets, such as if daylight saving or summer time is in effect. You can also specify an effective timestamp to\nretrieve the UTC offsets at a point in the past or future. Check out the\n[documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Ftz\u002F){target=\"_blank\"} for the full details.\n\n### Get Stated with the Time Zone API\n\nWe can&rsquo;t wait to see what you build with our new Time Zone API. To get you started, we&rsquo;ve written up a fresh\nPython tutorial in our [documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Ftz\u002F){target=\"_blank\"}.\n\n## Documentation Refresh\n\nSpeaking of docs, we recently gave our [docs](https:\u002F\u002Fdocs.stadiamaps.com\u002F){target=\"_blank\"}.\na long-overdue facelift, in large part thanks to [Material for MkDocs](https:\u002F\u002Fsquidfunk.github.io\u002Fmkdocs-material\u002F){target=\"_blank\"}\n(which we now \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fsponsors\u002Fsquidfunk\" target=\"_blank\">sponsor\u003C\u002Fa>). This is a\n*massive* upgrade which includes dark mode, better looking code blocks, improved navigation, and more.\n\nWe&rsquo;ve also added a full [API reference](https:\u002F\u002Fdocs.stadiamaps.com\u002Fapi-reference\u002F) that makes it easier to see\nall the endpoints we offer, along with comprehensive schema documentation. The new reference is generated from\nan \u003Ca href=\"https:\u002F\u002Fapi.stadiamaps.com\u002Fopenapi.yaml\" target=\"_blank\">OpenAPI specification\u003C\u002Fa>,\nwhich we will keep up to date as we add new endpoints. This machine-readable spec\ncan be used to generate an up-to-date API client in any major programming language, and allows us to provide you\nwith the new handy online API explorer.\n\n\n## Talk to us!\n\nWhat else do you want to do with our APIs? We&rsquo;re always happy to\nhear what else we can do for you or just learn about what\nyou&rsquo;re working on! You can get in touch via\n\u003Ca href=\"mailto:support@stadiamaps.com\">email\u003C\u002Fa> or the social links\nbelow.\n",{"title":7405,"description":7514},"blog\u002Fproduct-updates-time-zones-and-docs","_EwgbbytPBST6DiTWAg2LbhesXjw0ajPhp1ttT7HlbQ",{"id":7526,"title":7527,"abstract":7,"author":7,"body":7528,"description":7544,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7545,"meta":7548,"modified":7,"navigation":187,"path":7549,"proficiencyLevel":7,"published":7550,"rawbody":7551,"schemaOrg":7,"schemaType":7,"seo":7552,"stem":7553,"__hash__":7554},"blog\u002Fblog\u002Fmapbox-gl-licensing-and-stadia-maps.md","Mapbox GL JS v2 Licensing and Stadia Maps",{"type":14,"value":7529,"toc":7542},[7530,7533,7536,7539],[17,7531,7527],{"id":7532},"mapbox-gl-js-v2-licensing-and-stadia-maps",[24,7534,7535],{},"Yesterday (Dec. 8th, 2020), in conjunction with the v2 release of the\nMapbox GL JS library, the code was re-licensed to require an active\ncommercial license and subscription agreement with Mapbox. As a result,\nif you are currently using Mapbox GL JS v1 with Stadia Map tiles and\nupgrade to v2, you will need to pay Mapbox (as well as Stadia Maps) for\nmap usage.",[24,7537,7538],{},"For now, please continue using Stadia Maps' map tiles with version v1.13 or\nbelow. Since these versions are fully open source and freely licensed, you\nwill not incur any additional charges and your maps will continue to function as\nexpected.",[24,7540,7541],{},"Stadia Maps is actively working to build consensus towards a\ncommunity-driven, fully-open and free fork of Mapbox GL JS v1, and we\nwill continue to support and collaborate on these efforts going forward.\nIf you’re a developer or an organization utilizing the Mapbox GL JS or\nGL Native libraries and are looking for an alternative, feel free to\nreach out. We will continue working together for a more open and more\naccessible open mapping ecosystem.",{"title":168,"searchDepth":169,"depth":169,"links":7543},[],"An Update on Mapbox GL JS v2 Licensing and Stadia Maps",[7546,7547,2746,6275],"Mapbox GL JS","Licensing",{},"\u002Fblog\u002Fmapbox-gl-licensing-and-stadia-maps","2020-12-09","---\ndescription: An Update on Mapbox GL JS v2 Licensing and Stadia Maps\npublished: 2020-12-09\nkeywords:\n  - Mapbox GL JS\n  - Licensing\n  - MapLibre\n  - Open Source\n---\n\n# Mapbox GL JS v2 Licensing and Stadia Maps\n\nYesterday (Dec. 8th, 2020), in conjunction with the v2 release of the\nMapbox GL JS library, the code was re-licensed to require an active\ncommercial license and subscription agreement with Mapbox. As a result,\nif you are currently using Mapbox GL JS v1 with Stadia Map tiles and\nupgrade to v2, you will need to pay Mapbox (as well as Stadia Maps) for\nmap usage.\n\nFor now, please continue using Stadia Maps&apos; map tiles with version v1.13 or\nbelow. Since these versions are fully open source and freely licensed, you\nwill not incur any additional charges and your maps will continue to function as\nexpected.\n\nStadia Maps is actively working to build consensus towards a\ncommunity-driven, fully-open and free fork of Mapbox GL JS v1, and we\nwill continue to support and collaborate on these efforts going forward.\nIf you&rsquo;re a developer or an organization utilizing the Mapbox GL JS or\nGL Native libraries and are looking for an alternative, feel free to\nreach out. We will continue working together for a more open and more\naccessible open mapping ecosystem.\n",{"title":7527,"description":7544},"blog\u002Fmapbox-gl-licensing-and-stadia-maps","x_eHLjOp3VVGQmnwm92EgvAtDgkEempt1ZHzLNsNX1U",{"id":7556,"title":7557,"abstract":7,"author":7,"body":7558,"description":7667,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7668,"meta":7670,"modified":7,"navigation":187,"path":7671,"proficiencyLevel":7,"published":7672,"rawbody":7673,"schemaOrg":7,"schemaType":7,"seo":7674,"stem":7675,"__hash__":7676},"blog\u002Fblog\u002Fproduct-updates-improved-tiles-new-tier.md","Product Update: Improved Tiles, a New Tier, and Stadia Maps News",{"type":14,"value":7559,"toc":7658},[7560,7563,7566,7570,7573,7579,7585,7589,7592,7595,7598,7602,7605,7609,7612,7615,7619,7637,7639,7642,7646,7649,7652,7655],[17,7561,7557],{"id":7562},"product-update-improved-tiles-a-new-tier-and-stadia-maps-news",[24,7564,7565],{},"It’s been a few months since we last updated you on what\nwe’ve been doing around Stadia Maps, and we’ve been able to\naccomplish quite a lot.",[28,7567,7569],{"id":7568},"new-tier-stadia-growth","New Tier: Stadia Growth",[24,7571,7572],{},"After talking with customers and looking at our pricing, we realized there was a hole between our Starter and Standard\ntiers.",[24,7574,7575,7576,458],{},"Enter: ",[611,7577,7578],{},"Stadia Growth",[24,7580,7581,7582,7584],{},"A tier to help you grow, without growing your bills too much. Your $50 \u002F month goes a long way: 75k map views and API\nrequests \u002F day, with all the same great service you’ve learned to count on. Take a look at\nour ",[35,7583,6966],{"href":148}," to see how it fits in.",[28,7586,7588],{"id":7587},"better-raster-tiles-static-maps","Better Raster Tiles & Static Maps",[24,7590,7591],{},"At the beginning of this year, we knew our raster tiles had occasional\nedge-case performance issues, some cropped labels, and other minor\nquality concerns. So, starting in January, we began working towards\nfixing these issues.",[24,7593,7594],{},"We started by directly integrating our raster rendering library into our\ncustom-built tile server (it was previously a separate service). By doing\nthis, we’ve been able to almost completely eliminate our\nworst-case tail performance for raster tiles and static maps. After\nseeing promising results during the initial integration, we began tuning\nthe tile server against production loads, and have been able to eliminate\nmore performance bottlenecks. In terms of numbers, our worst-case raster\ntile rendering performance (the worst 0.1% of tile renders) dropped from\n8s to 2s—or 4x faster. At the same time, the 5% worst-case\nperforming requests improved from 512ms to 256ms—or 2x faster. We\nbelieve we have more progress to make, but this represents a significant\nstep towards eliminating too-slow tile renders.",[24,7596,7597],{},"As a very nice by-product, we’ve been able to drastically improve\nthe quality of our raster tiles (significantly fewer “cut\nlabels” and much better text layout). We are continuing to focus\non speed and reliability to ensure the best possible raster map\nexperience possible. Stay tuned for more updates regarding quality and\nperformance in the next few months.",[28,7599,7601],{"id":7600},"improved-outdoors-theme","Improved Outdoors Theme",[24,7603,7604],{},"Since our last update, we’ve added the ability to display parks\nand nature reserves over water, sand and rock land cover types to give\nbeaches and mountain ranges more texture, and—a much requested\nfeature—trails and footpaths at lower zoom levels, all so that you can\nenjoy the great outdoors just a little bit more.",[28,7606,7608],{"id":7607},"newer-data-better-depth","Newer Data, Better Depth",[24,7610,7611],{},"Another focus this year is to improve our processes for working with OSM\ndata. As a result, we’re on track to release new data each month this\nyear, with an improved schema each time. We’ve also increased the speed\nof our routing data updates, with new data being added every week.",[24,7613,7614],{},"Since January, we’ve added a lot of updates to details of the\ntransportation layer (including the trails and footpaths at higher\nzoom), improved small details to the water and park layers, and improved\nvector tile performance for higher zoom levels (especially in complex\ncityscapes, such as Milan or Tokyo).",[28,7616,7618],{"id":7617},"news-from-around-the-web","News from Around the Web",[24,7620,7621,7622,7626,7627,7631,7632,7636],{},"Over the last few months, we’ve had the chance to read about how\nsome of our customers are\n",[35,7623,7625],{"href":7624},"https:\u002F\u002Fmedium.com\u002F@onthegomap\u002Fon-the-go-map-style-improvements-d24bfb5836e1","\nusing Stadia Maps to improve their customers’ experiences\n",",\nthe opportunity to ",[35,7628,7630],{"href":7629},"https:\u002F\u002Fwww.tfir.io\u002Fstadia-maps\u002F","\nchat with TFIR about how to build better open-source mapping services\n",", and\nexplore ",[35,7633,7635],{"href":7634},"https:\u002F\u002Fwww.linode.com\u002Fspotlight\u002Fstadia-maps\u002F","\nhow we deliver a quality experience for an affordable price\n"," with our infrastructure provider, Linode.",[28,7638,1435],{"id":964},[24,7640,7641],{},"In the next couple of months, we will continue to squash remaining\nperformance and quality issues with raster tiles. We are working to hone\nour data schema to allow for better display of data (specifically more\nupgrades to the road network to eliminate some holes in our data). We\nare also close to deploying a new set of geospatial APIs (a time zone API\nwith historical data), after a few setbacks delivering it to production.",[28,7643,7645],{"id":7644},"missing-something-have-comments-or-concerns","Missing something? Have comments or concerns?",[24,7647,7648],{},"We’re always here to help. If you have any questions or concerns about\nour current services or our future roadmap, don’t hesitate to reach out\nto us with any of the channels listed in the footer. Of course, you can\nalways email us, we’ll get back to you lickety-split!",[24,7650,7651],{},"That’s all for now.",[24,7653,7654],{},"Stay well and be kind.",[24,7656,7657],{},"✌",{"title":168,"searchDepth":169,"depth":169,"links":7659},[7660,7661,7662,7663,7664,7665,7666],{"id":7568,"depth":172,"text":7569},{"id":7587,"depth":172,"text":7588},{"id":7600,"depth":172,"text":7601},{"id":7607,"depth":172,"text":7608},{"id":7617,"depth":172,"text":7618},{"id":964,"depth":172,"text":1435},{"id":7644,"depth":172,"text":7645},"Product Update: improved map tiles, a new pricing tier, and more news from about the web.",[7669,3184,7517],"Map Tiles",{},"\u002Fblog\u002Fproduct-updates-improved-tiles-new-tier","2020-07-02","---\npublished: 2020-07-02\ndescription: \"Product Update: improved map tiles, a new pricing tier, and more news from about the web.\"\nkeywords:\n  - Map Tiles\n  - Pricing\n  - Product Update\n---\n\n# Product Update: Improved Tiles, a New Tier, and Stadia Maps News\n\nIt&rsquo;s been a few months since we last updated you on what\nwe&rsquo;ve been doing around Stadia Maps, and we&rsquo;ve been able to\naccomplish quite a lot.\n\n## New Tier: Stadia Growth\n\nAfter talking with customers and looking at our pricing, we realized there was a hole between our Starter and Standard\ntiers.\n\nEnter: *Stadia Growth*.\n\nA tier to help you grow, without growing your bills too much. Your $50 \u002F month goes a long way: 75k map views and API\nrequests \u002F day, with all the same great service you&rsquo;ve learned to count on. Take a look at\nour [pricing page](\u002Fpricing\u002F) to see how it fits in.\n\n## Better Raster Tiles & Static Maps\n\nAt the beginning of this year, we knew our raster tiles had occasional\nedge-case performance issues, some cropped labels, and other minor\nquality concerns. So, starting in January, we began working towards\nfixing these issues.\n\nWe started by directly integrating our raster rendering library into our\ncustom-built tile server (it was previously a separate service). By doing\nthis, we&rsquo;ve been able to almost completely eliminate our\nworst-case tail performance for raster tiles and static maps. After\nseeing promising results during the initial integration, we began tuning\nthe tile server against production loads, and have been able to eliminate\nmore performance bottlenecks. In terms of numbers, our worst-case raster\ntile rendering performance (the worst 0.1% of tile renders) dropped from\n8s to 2s&mdash;or 4x faster. At the same time, the 5% worst-case\nperforming requests improved from 512ms to 256ms&mdash;or 2x faster. We\nbelieve we have more progress to make, but this represents a significant\nstep towards eliminating too-slow tile renders.\n\nAs a very nice by-product, we&rsquo;ve been able to drastically improve\nthe quality of our raster tiles (significantly fewer &ldquo;cut\nlabels&rdquo; and much better text layout). We are continuing to focus\non speed and reliability to ensure the best possible raster map\nexperience possible. Stay tuned for more updates regarding quality and\nperformance in the next few months.\n\n## Improved Outdoors Theme\n\nSince our last update, we&rsquo;ve added the ability to display parks\nand nature reserves over water, sand and rock land cover types to give\nbeaches and mountain ranges more texture, and&mdash;a much requested\nfeature&mdash;trails and footpaths at lower zoom levels, all so that you can\nenjoy the great outdoors just a little bit more.\n\n## Newer Data, Better Depth\n\nAnother focus this year is to improve our processes for working with OSM\ndata. As a result, we&rsquo;re on track to release new data each month this\nyear, with an improved schema each time. We&rsquo;ve also increased the speed\nof our routing data updates, with new data being added every week.\n\nSince January, we&rsquo;ve added a lot of updates to details of the\ntransportation layer (including the trails and footpaths at higher\nzoom), improved small details to the water and park layers, and improved\nvector tile performance for higher zoom levels (especially in complex\ncityscapes, such as Milan or Tokyo).\n\n## News from Around the Web\n\nOver the last few months, we&rsquo;ve had the chance to read about how\nsome of our customers are\n\u003Ca href=\"https:\u002F\u002Fmedium.com\u002F@onthegomap\u002Fon-the-go-map-style-improvements-d24bfb5836e1\">\n  using Stadia Maps to improve their customers&rsquo; experiences\n\u003C\u002Fa>,\nthe opportunity to \u003Ca href=\"https:\u002F\u002Fwww.tfir.io\u002Fstadia-maps\u002F\">\n  chat with TFIR about how to build better open-source mapping services\n\u003C\u002Fa>, and\nexplore \u003Ca href=\"https:\u002F\u002Fwww.linode.com\u002Fspotlight\u002Fstadia-maps\u002F\">\n  how we deliver a quality experience for an affordable price\n\u003C\u002Fa> with our infrastructure provider, Linode.\n\n## What's Next?\n\nIn the next couple of months, we will continue to squash remaining\nperformance and quality issues with raster tiles. We are working to hone\nour data schema to allow for better display of data (specifically more\nupgrades to the road network to eliminate some holes in our data). We\nare also close to deploying a new set of geospatial APIs (a time zone API\nwith historical data), after a few setbacks delivering it to production.\n\n## Missing something? Have comments or concerns?\n\nWe&rsquo;re always here to help. If you have any questions or concerns about\nour current services or our future roadmap, don&rsquo;t hesitate to reach out\nto us with any of the channels listed in the footer. Of course, you can\nalways email us, we&rsquo;ll get back to you lickety-split!\n\nThat&rsquo;s all for now.\n\nStay well and be kind.\n\n:v:",{"title":7557,"description":7667},"blog\u002Fproduct-updates-improved-tiles-new-tier","7pIh0gfqTjhEKCxAOI0MbZbg2PzIK4gqiSGysYfNUb0",{"id":7678,"title":7679,"abstract":7,"author":7,"body":7680,"description":7818,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7819,"meta":7823,"modified":7,"navigation":187,"path":7824,"proficiencyLevel":7,"published":7825,"rawbody":7826,"schemaOrg":7,"schemaType":7,"seo":7827,"stem":7828,"__hash__":7829},"blog\u002Fblog\u002Fmaps-before-during-after-covid-19.md","Helping Businesses Deliver Location Experiences Before, During, and After COVID-19",{"type":14,"value":7681,"toc":7808},[7682,7685,7688,7699,7702,7706,7709,7712,7716,7734,7738,7741,7752,7755,7758,7762,7765,7769,7777,7784,7787,7790,7795],[17,7683,7679],{"id":7684},"helping-businesses-deliver-location-experiences-before-during-and-after-covid-19",[24,7686,7687],{},"The impact of COVID-19, directly as a health crisis and indirectly as an\neconomic crisis, are widespread, deep, and likely to alter the landscape\nof the world. As Bob Dylan so elegantly sang in 1963: “The times they\nare a-changin'.”",[24,7689,7690,7691,7698],{},"The situation is critical for many small businesses as lockdowns and\nstay-at-home orders loom larger. Two months of missing (or substantially\nreduced) revenues would force 17% of businesses to close, 30% of\nbusinesses to eliminate expenses or defer payments, and almost 50% of\nbusinesses to tap into owners' own money to stay afloat.",[7692,7693,7694],"sup",{},[35,7695,7697],{"href":7696},"#footnote-1","1","\nNot knowing what tomorrow brings means businesses must adjust to a\ndrastically different world.",[24,7700,7701],{},"Stadia Maps began in 2016 because a small business couldn't deliver\na map to its customers without unsustainable costs. As a result, we\nspent the last 4 years building a platform that allows businesses to\nmaintain location-based services without the uncertainties of volatile\nbills, compromising customers' privacy, or curtailing the services\noffered.  Today, our services are uniquely positioned to give your\nbusiness a path forward with online maps and navigation—whether\nyou are struggling to justify hundreds or thousands of dollars in\nmonthly bills and looking for a more affordable option, or just seeking\na solution that better fits your mission.",[28,7703,7705],{"id":7704},"location-data-is-vital-but-it-neednt-be-expensive","Location data is vital, but it needn’t be expensive.",[24,7707,7708],{},"Maps are vital in today's changing world—in quarantine now\nand in the future as companies adapt to the new landscape. In fact, for\nsome industries, being able to effectively use location data is the\ndifference between meeting increased demand or failing to deliver. In\nthe world of logistics, delivering a package without ever seeing its\npath of travel on the map is unthinkable. Delivery companies, couriers\nservices, and many others rely on being able to effectively plan for\ndeliveries. Usually that means putting it all on a map and routing an\nassortment of trucks, bikes, and scooters so that people can get the\nnecessary goods of daily life, from food and soap to books and exercise\nequipment.",[24,7710,7711],{},"We believe that because maps and navigation are critical to many\nbusinesses, they should be affordable. Increased (or decreased) demand\nshouldn't put your company in a place where you have to choose\nbetween effective location services and keeping the doors open.",[28,7713,7715],{"id":7714},"change-is-afoot","Change is afoot.",[24,7717,7718,7719,7723,7724,7728,7729,7733],{},"Companies around the world are seeing fortunes made and lost because of\nCOVID-19. One such company, ",[35,7720,7722],{"href":7721},"https:\u002F\u002Fsaisonbox.ch","Saisonbox",",\nbased in St. Gallen, Switzerland, is\n",[35,7725,7727],{"href":7726},"https:\u002F\u002Fwww.tagblatt.ch\u002Fostschweiz\u002Fstgallen\u002Fgossauer-saisonbox-wird-dank-coronakrise-zum-bestseller-so-lockt-ein-kreatives-junges-bauernpaar-neue-kundinnen-ins-abgelegene-maedertal-ld.1208555","seeing business booming"," (link in German) as a result of COVID-19.\nTheir vegetable delivery service and direct-from-farm store allows\nindividuals to order fresh vegetables and fruits direct to their home.\nUnfortunately, other companies are experiencing seesawing demand and\nchaos that leads to instability and unexpected closure. Beaver Express,\na trucking and logistics company in Oklahoma,\n",[35,7730,7732],{"href":7731},"https:\u002F\u002Fwww.kscbnews.net\u002Fbeaver-express-to-close-its-doors\u002F","\nclosed last month"," after operating for 77 years. The “perfect\nstorm” of COVID-19 was too much for this small business.",[28,7735,7737],{"id":7736},"today-and-the-future","Today (and the Future)",[24,7739,7740],{},"Back to Dylan. He didn't stop by saying the times were changing; he\nwent on to sing about the battle born of those changing times:",[21,7742,7743],{},[24,7744,7745,7746,7748,7749,7751],{},"There’s a battle outside, and it is ragin'",[2995,7747],{},"\nIt’ll soon shake your windows and rattle your walls",[2995,7750],{},"\nFor the times they are a-changin'",[24,7753,7754],{},"COVID-19 is shaking our windows and rattling our walls—as a world,\nas communities, as businesses, and as individuals. It's affecting\nour nerves.  It's stressing us out. We're all fighting\nbattles, big and small, to keep ourselves, our families, and our\ncompanies together during this time.",[24,7756,7757],{},"The world will get through this—of that there is no doubt—but it will\nsee enormous change. Stadia Maps believes we can help businesses be a\npart of positive change by offering mapping solutions based on open\ndata, respecting user privacy, and offering a more accessible and more\naffordable product.",[28,7759,7761],{"id":7760},"were-here-to-help","We're here to help.",[24,7763,7764],{},"If your company is struggling with burdensome location data bills, or\nyou are considering removing or hiding location features because\nthey're too expensive to offer, take a look at Stadia Maps.",[1205,7766,7768],{"id":7767},"free-or-discounted-services","Free or Discounted Services",[24,7770,7771,7772,7776],{},"If you have a project that is directly used in efforts to combat\nCOVID-19, we offer discounts of 50%–100% for these projects. For\nexample: we're pleased to support the\n",[35,7773,7775],{"href":7774},"https:\u002F\u002Fgithub.com\u002FBustByte\u002Fcoronastatus\u002F","\nCoronastatus project\n",", a tool to help track symptoms across countries. Just contact us if\nyour project needs maps or navigation.",[28,7778,7780,7781],{"id":7779},"be-human-yall2","Be human, y'all.",[7692,7782,7783],{},"2",[24,7785,7786],{},"In the end, choosing the right mapping solution pales in comparison to\nthe effects of this worldwide pandemic. While we are doing all we can to\noffer helpful location solutions for businesses, we believe that you and\nyour actions—as fellow humans—are the true key to a better\nfuture, after the pandemic has passed. We grieve the impact of COVID-19\nacross the world: loss of employment, loss of company, and loss of life,\nand we urge you to do everything you can to be kind, be helpful, and be\nthere for others during this time.",[24,7788,7789],{},"Stay well, and stay home. ✌",[24,7791,7792],{},[62,7793,7794],{},"Notes:",[107,7796,7797,7805],{},[59,7798,7799,7800,7804],{},"These figures were reported by the Federal Reserve in a\nrecent ",[35,7801,7803],{"href":7802},"https:\u002F\u002Fwww.fedsmallbusiness.org\u002Fmedialibrary\u002FFedSmallBusiness\u002Ffiles\u002F2020\u002F2020-sbcs-employer-firms-report","\nstudy of small businesses "," in the US.",[59,7806,7807],{},"For our friends not from the Southern US: “Y'all” is short for “you all” or “everyone.”",{"title":168,"searchDepth":169,"depth":169,"links":7809},[7810,7811,7812,7813,7816],{"id":7704,"depth":172,"text":7705},{"id":7714,"depth":172,"text":7715},{"id":7736,"depth":172,"text":7737},{"id":7760,"depth":172,"text":7761,"children":7814},[7815],{"id":7767,"depth":669,"text":7768},{"id":7779,"depth":172,"text":7817},"Be human, y'all.2","How we are helping businesses deliver location experiences before, during, and after COVID-19.",[7820,7821,7822],"COVID-19","Business Continuity","Location Services",{},"\u002Fblog\u002Fmaps-before-during-after-covid-19","2020-04-15","---\npublished: 2020-04-15\ndescription: How we are helping businesses deliver location experiences before, during, and after COVID-19.\nkeywords:\n  - COVID-19\n  - Business Continuity\n  - Location Services\n---\n\n# Helping Businesses Deliver Location Experiences Before, During, and After COVID-19\n\nThe impact of COVID-19, directly as a health crisis and indirectly as an\neconomic crisis, are widespread, deep, and likely to alter the landscape\nof the world. As Bob Dylan so elegantly sang in 1963: &ldquo;The times they\nare a-changin&apos;.&rdquo;\n\nThe situation is critical for many small businesses as lockdowns and\nstay-at-home orders loom larger. Two months of missing (or substantially\nreduced) revenues would force 17% of businesses to close, 30% of\nbusinesses to eliminate expenses or defer payments, and almost 50% of\nbusinesses to tap into owners&apos; own money to stay afloat.\u003Csup>\n  \u003Ca href=\"#footnote-1\">1\u003C\u002Fa>\n\u003C\u002Fsup>\nNot knowing what tomorrow brings means businesses must adjust to a\ndrastically different world.\n\nStadia Maps began in 2016 because a small business couldn&apos;t deliver\na map to its customers without unsustainable costs. As a result, we\nspent the last 4 years building a platform that allows businesses to\nmaintain location-based services without the uncertainties of volatile\nbills, compromising customers&apos; privacy, or curtailing the services\noffered.  Today, our services are uniquely positioned to give your\nbusiness a path forward with online maps and navigation&mdash;whether\nyou are struggling to justify hundreds or thousands of dollars in\nmonthly bills and looking for a more affordable option, or just seeking\na solution that better fits your mission.\n\n## Location data is vital, but it needn’t be expensive.\n\nMaps are vital in today&apos;s changing world&mdash;in quarantine now\nand in the future as companies adapt to the new landscape. In fact, for\nsome industries, being able to effectively use location data is the\ndifference between meeting increased demand or failing to deliver. In\nthe world of logistics, delivering a package without ever seeing its\npath of travel on the map is unthinkable. Delivery companies, couriers\nservices, and many others rely on being able to effectively plan for\ndeliveries. Usually that means putting it all on a map and routing an\nassortment of trucks, bikes, and scooters so that people can get the\nnecessary goods of daily life, from food and soap to books and exercise\nequipment.\n\nWe believe that because maps and navigation are critical to many\nbusinesses, they should be affordable. Increased (or decreased) demand\nshouldn&apos;t put your company in a place where you have to choose\nbetween effective location services and keeping the doors open.\n\n## Change is afoot.\n\nCompanies around the world are seeing fortunes made and lost because of\nCOVID-19. One such company, \u003Ca href=\"https:\u002F\u002Fsaisonbox.ch\">Saisonbox\u003C\u002Fa>,\nbased in St. Gallen, Switzerland, is\n\u003Ca href=\"https:\u002F\u002Fwww.tagblatt.ch\u002Fostschweiz\u002Fstgallen\u002Fgossauer-saisonbox-wird-dank-coronakrise-zum-bestseller-so-lockt-ein-kreatives-junges-bauernpaar-neue-kundinnen-ins-abgelegene-maedertal-ld.1208555\">seeing business booming\u003C\u002Fa> (link in German) as a result of COVID-19.\nTheir vegetable delivery service and direct-from-farm store allows\nindividuals to order fresh vegetables and fruits direct to their home.\nUnfortunately, other companies are experiencing seesawing demand and\nchaos that leads to instability and unexpected closure. Beaver Express,\na trucking and logistics company in Oklahoma,\n\u003Ca href=\"https:\u002F\u002Fwww.kscbnews.net\u002Fbeaver-express-to-close-its-doors\u002F\">\n  closed last month\u003C\u002Fa> after operating for 77 years. The &ldquo;perfect\nstorm&rdquo; of COVID-19 was too much for this small business.\n\n## Today (and the Future)\n\nBack to Dylan. He didn&apos;t stop by saying the times were changing; he\nwent on to sing about the battle born of those changing times:\n\n>   There’s a battle outside, and it is ragin&apos;\u003Cbr \u002F>\n>   It’ll soon shake your windows and rattle your walls\u003Cbr \u002F>\n>   For the times they are a-changin&apos;\n> \nCOVID-19 is shaking our windows and rattling our walls&mdash;as a world,\nas communities, as businesses, and as individuals. It&apos;s affecting\nour nerves.  It&apos;s stressing us out. We&apos;re all fighting\nbattles, big and small, to keep ourselves, our families, and our\ncompanies together during this time.\n\nThe world will get through this&mdash;of that there is no doubt&mdash;but it will\nsee enormous change. Stadia Maps believes we can help businesses be a\npart of positive change by offering mapping solutions based on open\ndata, respecting user privacy, and offering a more accessible and more\naffordable product.\n\n## We&apos;re here to help.\n\nIf your company is struggling with burdensome location data bills, or\nyou are considering removing or hiding location features because\nthey&apos;re too expensive to offer, take a look at Stadia Maps.\n\n### Free or Discounted Services\n\nIf you have a project that is directly used in efforts to combat\nCOVID-19, we offer discounts of 50%&ndash;100% for these projects. For\nexample: we&apos;re pleased to support the\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FBustByte\u002Fcoronastatus\u002F\">\n  Coronastatus project\n\u003C\u002Fa>, a tool to help track symptoms across countries. Just contact us if\nyour project needs maps or navigation.\n\n## Be human, y&apos;all.\u003Csup>2\u003C\u002Fsup>\n\nIn the end, choosing the right mapping solution pales in comparison to\nthe effects of this worldwide pandemic. While we are doing all we can to\noffer helpful location solutions for businesses, we believe that you and\nyour actions&mdash;as fellow humans&mdash;are the true key to a better\nfuture, after the pandemic has passed. We grieve the impact of COVID-19\nacross the world: loss of employment, loss of company, and loss of life,\nand we urge you to do everything you can to be kind, be helpful, and be\nthere for others during this time. \n\nStay well, and stay home. :v:\n\n**Notes:**\n\n1. These figures were reported by the Federal Reserve in a\n   recent \u003Ca href=\"https:\u002F\u002Fwww.fedsmallbusiness.org\u002Fmedialibrary\u002FFedSmallBusiness\u002Ffiles\u002F2020\u002F2020-sbcs-employer-firms-report\">\n   study of small businesses \u003C\u002Fa> in the US.\n2. For our friends not from the Southern US: &ldquo;Y&apos;all&rdquo; is short for &ldquo;you all&rdquo; or &ldquo;everyone.&rdquo;",{"title":7679,"description":7818},"blog\u002Fmaps-before-during-after-covid-19","Yf3N_YHobYBsIgffyavwUeYDK2DSvFYQQSPZUzsVWvI",{"id":7831,"title":7832,"abstract":7,"author":7,"body":7833,"description":7893,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7894,"meta":7896,"modified":7,"navigation":187,"path":7898,"proficiencyLevel":7,"published":7899,"rawbody":7900,"schemaOrg":7,"schemaType":7,"seo":7901,"stem":7902,"__hash__":7903},"blog\u002Fblog\u002Fenhanced-docs-and-mkjsfiddle.md","Enhanced Documentation and Introducing mkjsfiddle",{"type":14,"value":7834,"toc":7889},[7835,7838,7841,7855,7863,7867,7882,7884],[17,7836,7832],{"id":7837},"enhanced-documentation-and-introducing-mkjsfiddle",[24,7839,7840],{},"At Stadia Maps, we work hard to make your mapping experience easy and painless. A core part of our mission to make\nlocation human is making our docs as accessible as possible for you as a developer. The fewer the hurdles to\ndevelopment, the faster you can deliver solutions to your customers.",[24,7842,7843,7844,7849,7850,7854],{},"Experimenting with code and seeing results instantly is an effective way to learn a new library or framework. If you’re\na frontend developer, there’s a good chance you have already used ",[35,7845,7848],{"href":7846,"rel":7847,"target":40},"https:\u002F\u002Fjsfiddle.net\u002F",[39],"JSFiddle"," for this a few\ntimes. We did some digging and found that they have\nan ",[35,7851,2970],{"href":7852,"rel":7853,"target":40},"https:\u002F\u002Fdocs.jsfiddle.net\u002Fapi\u002Fdisplay-a-fiddle-from-post",[39],", which lets us generate fiddles from the code\nsegments in our docs, freeing you to focus on what matters. No need to copy the code to your computer, start up a web\nserver, or register an account—just start fiddling!",[24,7856,7857,7858,3461],{},"We've updated the relevant code snippets in our docs, such as vector and raster map examples, with a nifty button to\nedit the sample right away in JSFiddle. Check it out in action ",[35,7859,7862],{"href":7860,"rel":7861,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Fvector\u002F",[39],"over here",[28,7864,7866],{"id":7865},"announcing-mkjsfiddle","Announcing mkjsfiddle",[24,7868,7869,7870,7875,7876,7881],{},"While we were building the integration, we looked around for a library that would do it automatically. We\nuse ",[35,7871,7874],{"href":7872,"rel":7873,"target":40},"https:\u002F\u002Fwww.mkdocs.org\u002F",[39],"MkDocs"," for generating our documentation pages from Markdown, and we thought surely\nsomeone would have a plugin for this already. Unfortunately we couldn’t find any, so we wrote one! We think other\nMkDocs-based sites can benefit from JSFiddle integration as well, so\nwe’ve ",[35,7877,7880],{"href":7878,"rel":7879,"target":40},"https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fmkjsfiddle",[39],"open-sourced our plugin",". We hope other projects can use this to make\ntheir docs a little more human.",[28,7883,7499],{"id":7498},[24,7885,7886,7887,7506],{},"Are our docs helping you easily find the information you need? Wish you could do something more with Stadia Maps? We’re\nalways happy to hear how we can improve! Let us know via ",[35,7888,7505],{"href":3838},{"title":168,"searchDepth":169,"depth":169,"links":7890},[7891,7892],{"id":7865,"depth":172,"text":7866},{"id":7498,"depth":172,"text":7499},"We've enhanced our documentation with JSFiddle integration and open-sourced the code we used to do it!",[7516,7848,6275,7895],"Developer Experience",{"subtitle":7897},"Better examples and an open source library!","\u002Fblog\u002Fenhanced-docs-and-mkjsfiddle","2020-03-04","---\nsubtitle: Better examples and an open source library!\npublished: 2020-03-04\ndescription: \"We've enhanced our documentation with JSFiddle integration and open-sourced the code we used to do it!\"\nkeywords:\n  - Documentation\n  - JSFiddle\n  - Open Source\n  - Developer Experience\n---\n\n# Enhanced Documentation and Introducing mkjsfiddle\n\nAt Stadia Maps, we work hard to make your mapping experience easy and painless. A core part of our mission to make\nlocation human is making our docs as accessible as possible for you as a developer. The fewer the hurdles to\ndevelopment, the faster you can deliver solutions to your customers.\n\nExperimenting with code and seeing results instantly is an effective way to learn a new library or framework. If you’re\na frontend developer, there’s a good chance you have already used [JSFiddle](https:\u002F\u002Fjsfiddle.net\u002F) for this a few\ntimes. We did some digging and found that they have\nan [API](https:\u002F\u002Fdocs.jsfiddle.net\u002Fapi\u002Fdisplay-a-fiddle-from-post), which lets us generate fiddles from the code\nsegments in our docs, freeing you to focus on what matters. No need to copy the code to your computer, start up a web\nserver, or register an account—just start fiddling!\n\nWe've updated the relevant code snippets in our docs, such as vector and raster map examples, with a nifty button to\nedit the sample right away in JSFiddle. Check it out in action [over here](https:\u002F\u002Fdocs.stadiamaps.com\u002Fvector\u002F)!\n\n## Announcing mkjsfiddle\n\nWhile we were building the integration, we looked around for a library that would do it automatically. We\nuse [MkDocs](https:\u002F\u002Fwww.mkdocs.org\u002F) for generating our documentation pages from Markdown, and we thought surely\nsomeone would have a plugin for this already. Unfortunately we couldn’t find any, so we wrote one! We think other\nMkDocs-based sites can benefit from JSFiddle integration as well, so\nwe’ve [open-sourced our plugin](https:\u002F\u002Fgithub.com\u002Fstadiamaps\u002Fmkjsfiddle). We hope other projects can use this to make\ntheir docs a little more human.\n\n## Talk to us!\n\nAre our docs helping you easily find the information you need? Wish you could do something more with Stadia Maps? We’re\nalways happy to hear how we can improve! Let us know via [email](mailto:support@stadiamaps.com) or the social links\nbelow.",{"title":7832,"description":7893},"blog\u002Fenhanced-docs-and-mkjsfiddle","N5uioRRARxmYcCoQXg9D8ss7A8FNn_MEGzd9lQlmJrU",{"id":7905,"title":7906,"abstract":7,"author":7,"body":7907,"description":7978,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":7979,"meta":7982,"modified":7,"navigation":187,"path":7983,"proficiencyLevel":7,"published":7984,"rawbody":7985,"schemaOrg":7,"schemaType":7,"seo":7986,"stem":7987,"__hash__":7988},"blog\u002Fblog\u002Fannouncing-elevation-data.md","Announcing Elevation Data",{"type":14,"value":7908,"toc":7970},[7909,7912,7921,7925,7928,7932,7935,7942,7951,7955,7962,7964],[17,7910,7906],{"id":7911},"announcing-elevation-data",[24,7913,7914,7915,7920],{},"Ever since we started offering our navigation API, we've received a slow, steady stream of requests for elevation data.\nWhile we really wanted to offer this, doing so, at the quality of service our customers deserve, requires a lot of disk\nspace. Given our global user base and commitment to affordable prices, we needed to find a solution that allowed us to\noffer world-wide elevation coverage without costing too much. Thanks to\nour ",[35,7916,7919],{"href":7917,"rel":7918,"target":40},"https:\u002F\u002Fwww.linode.com\u002Fproducts\u002Fobject-storage\u002F",[39],"cloud provider's new Object Storage"," offering, we developed a\nperformant solution that enables us to deliver global elevation data without raising prices. We finished beta testing a\nfew weeks ago, and are excited to announce that Valhalla-powered elevation APIs are now live!",[28,7922,7924],{"id":7923},"elevation-dataat-a-point-or-along-a-path","Elevation data—at a point or along a path",[24,7926,7927],{},"Elevation data is a perfect companion to route planning, especially for\nrunners and cyclists. In addition to getting the elevation at a single\npoint, you can also ask for the elevation along a path (such as a\ncycling route) and use this data to display a route profile for a\nplanned route.",[28,7929,7931],{"id":7930},"elevation-influenced-routing-for-bicycles","Elevation-influenced Routing for Bicycles",[24,7933,7934],{},"Additionally, bicycle routing can now specify a hill usage penalty. This gives most cyclists outside Switzerland the\noption to flatten out the ride a bit. For those of you in the Swiss alps, we can’t promise too much. ⛰:flag-ch:",[28,7936,7938,7939],{"id":7937},"introducing-apistadiamapscom","Introducing ",[349,7940,7941],{},"api.stadiamaps.com",[24,7943,7944,7945,7948,7949,458],{},"We're also excited to announce a new hostname that you can use for accessing all of our APIs. ",[349,7946,7947],{},"route.stadiamaps.com","\nserved its purpose well when we only offered routing APIs, but as we grow, we feel it’s time to make the\ntransition to a more general hostname for all of our geospatial APIs: api.stadiamaps.com. We will, of course, continue\nsupporting existing services running on the old subdomain, but the forthcoming geospatial APIs will only be accessible\nvia ",[349,7950,7941],{},[28,7952,7954],{"id":7953},"get-stated-with-elevation-data","Get Stated with Elevation Data",[24,7956,7957,7958,3461],{},"Want to dive right into using elevation data? Learn more over in our\n",[35,7959,165],{"href":7960,"rel":7961,"target":40},"https:\u002F\u002Fdocs.stadiamaps.com\u002Felevation%22%3Edocumentation",[39],[28,7963,7499],{"id":7498},[24,7965,7966,7967,7969],{},"Is our routing service missing something? Wish you could do something more with Stadia Maps? We’re always happy to\nhear how we can improve! Let us know via ",[35,7968,7505],{"href":3838}," or the social links below.",{"title":168,"searchDepth":169,"depth":169,"links":7971},[7972,7973,7974,7976,7977],{"id":7923,"depth":172,"text":7924},{"id":7930,"depth":172,"text":7931},{"id":7937,"depth":172,"text":7975},"Introducing api.stadiamaps.com",{"id":7953,"depth":172,"text":7954},{"id":7498,"depth":172,"text":7499},"Taking our services to the next level: elevation data at a point, along a path, and for elevation-influenced routing.",[7980,7981,179,6999],"Elevation Data","Terrain",{},"\u002Fblog\u002Fannouncing-elevation-data","2019-11-06","---\npublished: 2019-11-06\ndescription: \"Taking our services to the next level: elevation data at a point, along a path, and for elevation-influenced routing.\"\nkeywords:\n  - Elevation Data\n  - Terrain\n  - Routing\n  - Product Launch\n---\n\n# Announcing Elevation Data\n\nEver since we started offering our navigation API, we've received a slow, steady stream of requests for elevation data.\nWhile we really wanted to offer this, doing so, at the quality of service our customers deserve, requires a lot of disk\nspace. Given our global user base and commitment to affordable prices, we needed to find a solution that allowed us to\noffer world-wide elevation coverage without costing too much. Thanks to\nour [cloud provider's new Object Storage](https:\u002F\u002Fwww.linode.com\u002Fproducts\u002Fobject-storage\u002F) offering, we developed a\nperformant solution that enables us to deliver global elevation data without raising prices. We finished beta testing a\nfew weeks ago, and are excited to announce that Valhalla-powered elevation APIs are now live!\n\n## Elevation data—at a point or along a path\n\nElevation data is a perfect companion to route planning, especially for\nrunners and cyclists. In addition to getting the elevation at a single\npoint, you can also ask for the elevation along a path (such as a\ncycling route) and use this data to display a route profile for a\nplanned route.\n\n## Elevation-influenced Routing for Bicycles\n\nAdditionally, bicycle routing can now specify a hill usage penalty. This gives most cyclists outside Switzerland the\noption to flatten out the ride a bit. For those of you in the Swiss alps, we can&rsquo;t promise too much. :mountain::flag-ch:\n\n## Introducing `api.stadiamaps.com`\n\nWe're also excited to announce a new hostname that you can use for accessing all of our APIs. `route.stadiamaps.com`\nserved its purpose well when we only offered routing APIs, but as we grow, we feel it&rsquo;s time to make the\ntransition to a more general hostname for all of our geospatial APIs: api.stadiamaps.com. We will, of course, continue\nsupporting existing services running on the old subdomain, but the forthcoming geospatial APIs will only be accessible\nvia `api.stadiamaps.com`.\n\n## Get Stated with Elevation Data\n\nWant to dive right into using elevation data? Learn more over in our\n[documentation](https:\u002F\u002Fdocs.stadiamaps.com\u002Felevation\">documentation)!\n\n## Talk to us!\n\nIs our routing service missing something? Wish you could do something more with Stadia Maps? We&rsquo;re always happy to\nhear how we can improve! Let us know via [email](mailto:support@stadiamaps.com) or the social links below.\n",{"title":7906,"description":7978},"blog\u002Fannouncing-elevation-data","Nh0LNQehzm9RnNZw4-4sZkC-e30pqGRBK2MtlGd3DF8",{"id":7990,"title":7991,"abstract":7,"author":7,"body":7992,"description":8135,"excerpt":7,"extension":177,"head":7,"image":7,"keywords":8136,"meta":8140,"modified":7,"navigation":187,"path":8141,"proficiencyLevel":7,"published":8142,"rawbody":8143,"schemaOrg":7,"schemaType":7,"seo":8144,"stem":8145,"__hash__":8146},"blog\u002Fblog\u002Finfrastructure-v2-improved-map-tiles-and-data.md","Mapping Infrastructure v2 Release",{"type":14,"value":7993,"toc":8125},[7994,7997,8000,8003,8006,8010,8014,8017,8021,8025,8028,8063,8066,8070,8074,8077,8080,8083,8087,8091,8094,8097,8100,8114,8117,8119],[17,7995,7991],{"id":7996},"mapping-infrastructure-v2-release",[24,7998,7999],{},"After months of painstaking development, testing, data gathering,\ndeployment and a few seconds to flip the switch, we are pleased to\nannounce Stadia's mapping data infrastructure, version 2!",[24,8001,8002],{},"Shortly after starting Stadia Maps in 2017, we realized our method of\nprocessing, development, and deployment of mapping data was limited. We\ncould not deliver the quality maps our customers need or our inner\nperfectionists demand. We wanted to quickly deploy updates and iterate\non designs to make our maps more useful and beautiful. We wanted to add\nnew features without months of lag from testing to production.\nUltimately, we wanted a platform that would allow us to deliver an\nimproved mapping experience every single day. So last year, we began\ninvesting in a new mapping infrastructure that could deliver all the\nfeatures we hoped for (plus a few new ones we’ve discovered along\nthe way). To accomplish that, we needed to control the pipeline all the\nway from ingesting source data to displaying the maps for our users.",[24,8004,8005],{},"As of today, our dream is reality and your maps are getting loads of\nimprovements, all because our mapping data is delivered from a pipeline\n100% managed by us.",[28,8007,8009],{"id":8008},"improvements","Improvements",[1205,8011,8013],{"id":8012},"data-updates","Data Updates",[24,8015,8016],{},"We are now delivering data from early August 2019, and plan to deliver at\nleast monthly updates to our underlying mapping data to allow you and your\ncustomers to have the latest data possible.",[1205,8018,8020],{"id":8019},"improved-language-support","Improved Language Support",[7207,8022],{"afterSrc":8023,"beforeSrc":8024},"\u002Fassets\u002F2019-new-tiles-language.png","\u002Fassets\u002F2019-old-tiles-language.png",[24,8026,8027],{},"We’ve added support for many new languages in our themes, and we have\nplans to add another major source of data to extend our language coverage\nto as many places and languages as possible. We’ve added the following\nlanguages and scripts to our themes (in alphabetical order):",[56,8029,8030,8033,8036,8039,8042,8045,8048,8051,8054,8057,8060],{},[59,8031,8032],{},"Armenian",[59,8034,8035],{},"Bengali",[59,8037,8038],{},"Devanagari",[59,8040,8041],{},"Ethiopian",[59,8043,8044],{},"Georgian",[59,8046,8047],{},"Hebrew",[59,8049,8050],{},"Khmer",[59,8052,8053],{},"Lao",[59,8055,8056],{},"Myanmar (Burmese)",[59,8058,8059],{},"Tamil",[59,8061,8062],{},"Thai",[24,8064,8065],{},"If you know of any language or script we don’t currently support, please\nlet us know!",[1205,8067,8069],{"id":8068},"extended-national-park-and-nature-reserve-coverage","Extended National Park and Nature Reserve Coverage",[7207,8071],{"afterSrc":8072,"beforeSrc":8073},"\u002Fassets\u002F2019-new-national.png","\u002Fassets\u002F2019-old-national.png",[24,8075,8076],{},"We believe our Outdoor theme is critical for our customers who focus on\neverything that happens outside the confines of a car or building. Until\ntoday, the Outdoor theme was missing a pretty critical piece of data:\nlabels for national parks and official nature reserves—the places we all\nenjoy hiking, biking, swimming, or just soaking in the aura of nature.",[24,8078,8079],{},"We also updated mountain peaks to include elevation data (where\navailable), and we made small tweaks to display mountain peaks more\noften and with somewhat better selection based on relative importance.\n(We believe there’s still room to improve this further in later\nupdates.)",[24,8081,8082],{},"Now you and your customers can go forth and enjoy nature—with\nfull awareness of what to call the place they are enjoying it.",[1205,8084,8086],{"id":8085},"improved-bay-and-water-label-visibility","Improved Bay and Water Label Visibility",[7207,8088],{"afterSrc":8089,"beforeSrc":8090},"\u002Fassets\u002F2019-new-water.png","\u002Fassets\u002F2019-old-water.png",[24,8092,8093],{},"Another important piece of location awareness is out to sea—more\nspecifically, bays and other smaller bodies of water. We’ve added\nlabels for smaller bays and waterways to make that favorite lagoon a bit\neasier to find.",[28,8095,8096],{"id":964},"What’s next?",[24,8098,8099],{},"We have a lot of updates on the heels the new pipeline. Because it allows\nquick iteration, we plan to add the following data to our core data and\nthemes as appropriate over the next few months:",[56,8101,8102,8105,8108,8111],{},[59,8103,8104],{},"Ocean Bathymetry",[59,8106,8107],{},"Contour lines",[59,8109,8110],{},"Hillshading",[59,8112,8113],{},"…and more!",[24,8115,8116],{},"We will soon be releasing our geospatial APIs (starting with elevation\nand time zones) and offer improved routing for bicycles based on the\nelevation data. We’re also hard at work developing our enterprise\nlevel plans to meet even the most demanding business needs.",[28,8118,7499],{"id":7498},[24,8120,8121,8122,8124],{},"And we want to hear from you! If there’s anything you need to make\nyour mapping experience more fantastic, just let us know. We’re\nalways ready to help and answer your questions at\n",[35,8123,3839],{"href":3838}," or your\nfavorite social channel (links in footer).",{"title":168,"searchDepth":169,"depth":169,"links":8126},[8127,8133,8134],{"id":8008,"depth":172,"text":8009,"children":8128},[8129,8130,8131,8132],{"id":8012,"depth":669,"text":8013},{"id":8019,"depth":669,"text":8020},{"id":8068,"depth":669,"text":8069},{"id":8085,"depth":669,"text":8086},{"id":964,"depth":172,"text":8096},{"id":7498,"depth":172,"text":7499},"A revamped mapping data pipeline, improved map data and themes, and a look to the future.",[8137,8138,8139,7669],"Infrastructure","Map Data","Data Pipeline",{},"\u002Fblog\u002Finfrastructure-v2-improved-map-tiles-and-data","2019-08-26","---\ndescription: A revamped mapping data pipeline, improved map data and themes, and a look to the future.\npublished: 2019-08-26\nkeywords:\n  - Infrastructure\n  - Map Data\n  - Data Pipeline\n  - Map Tiles\n---\n\n# Mapping Infrastructure v2 Release\n\nAfter months of painstaking development, testing, data gathering,\ndeployment and a few seconds to flip the switch, we are pleased to\nannounce Stadia's mapping data infrastructure, version 2!\n\nShortly after starting Stadia Maps in 2017, we realized our method of\nprocessing, development, and deployment of mapping data was limited. We\ncould not deliver the quality maps our customers need or our inner\nperfectionists demand. We wanted to quickly deploy updates and iterate\non designs to make our maps more useful and beautiful. We wanted to add\nnew features without months of lag from testing to production.\nUltimately, we wanted a platform that would allow us to deliver an\nimproved mapping experience every single day. So last year, we began\ninvesting in a new mapping infrastructure that could deliver all the\nfeatures we hoped for (plus a few new ones we&rsquo;ve discovered along\nthe way). To accomplish that, we needed to control the pipeline all the\nway from ingesting source data to displaying the maps for our users.\n\nAs of today, our dream is reality and your maps are getting loads of\nimprovements, all because our mapping data is delivered from a pipeline\n100% managed by us.\n\n## Improvements\n\n### Data Updates\n\nWe are now delivering data from early August 2019, and plan to deliver at\nleast monthly updates to our underlying mapping data to allow you and your\ncustomers to have the latest data possible.\n\n### Improved Language Support\n\n::content-twenty-twenty\n---\nbeforeSrc: \"\u002Fassets\u002F2019-old-tiles-language.png\"\nafterSrc: \"\u002Fassets\u002F2019-new-tiles-language.png\"\n---\n::\n\nWe&rsquo;ve added support for many new languages in our themes, and we have\nplans to add another major source of data to extend our language coverage\nto as many places and languages as possible. We&rsquo;ve added the following\nlanguages and scripts to our themes (in alphabetical order):\n\n* Armenian\n* Bengali\n* Devanagari\n* Ethiopian\n* Georgian\n* Hebrew\n* Khmer\n* Lao\n* Myanmar (Burmese)\n* Tamil\n* Thai\n \nIf you know of any language or script we don&rsquo;t currently support, please\nlet us know!\n\n### Extended National Park and Nature Reserve Coverage\n\n::content-twenty-twenty\n---\nbeforeSrc: \"\u002Fassets\u002F2019-old-national.png\"\nafterSrc: \"\u002Fassets\u002F2019-new-national.png\"\n---\n::\n\nWe believe our Outdoor theme is critical for our customers who focus on\neverything that happens outside the confines of a car or building. Until\ntoday, the Outdoor theme was missing a pretty critical piece of data:\nlabels for national parks and official nature reserves&mdash;the places we all\nenjoy hiking, biking, swimming, or just soaking in the aura of nature.\n\nWe also updated mountain peaks to include elevation data (where\navailable), and we made small tweaks to display mountain peaks more\noften and with somewhat better selection based on relative importance.\n(We believe there&rsquo;s still room to improve this further in later\nupdates.)\n\nNow you and your customers can go forth and enjoy nature&mdash;with\nfull awareness of what to call the place they are enjoying it.\n\n### Improved Bay and Water Label Visibility\n\n::content-twenty-twenty\n---\nbeforeSrc: \"\u002Fassets\u002F2019-old-water.png\"\nafterSrc: \"\u002Fassets\u002F2019-new-water.png\"\n---\n::\n\nAnother important piece of location awareness is out to sea&mdash;more\nspecifically, bays and other smaller bodies of water. We&rsquo;ve added\nlabels for smaller bays and waterways to make that favorite lagoon a bit\neasier to find.\n\n## What&rsquo;s next?\n\nWe have a lot of updates on the heels the new pipeline. Because it allows\nquick iteration, we plan to add the following data to our core data and\nthemes as appropriate over the next few months:\n\n* Ocean Bathymetry\n* Contour lines\n* Hillshading\n* &hellip;and more!\n \nWe will soon be releasing our geospatial APIs (starting with elevation\nand time zones) and offer improved routing for bicycles based on the\nelevation data. We&rsquo;re also hard at work developing our enterprise\nlevel plans to meet even the most demanding business needs.\n\n## Talk to us!\n\nAnd we want to hear from you! If there&rsquo;s anything you need to make\nyour mapping experience more fantastic, just let us know. We&rsquo;re\nalways ready to help and answer your questions at\n[support@stadiamaps.com](mailto:support@stadiamaps.com) or your\nfavorite social channel (links in footer).",{"title":7991,"description":8135},"blog\u002Finfrastructure-v2-improved-map-tiles-and-data","9E1NInDHqiwL5MBOe_DQkS0UKqlB-l98Wrg5tlPmwrk",1778676024258]