[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-\u002Fblog\u002Fplss-api-for-og-lease-databases-geocoding-legal-descriptions-at-scale":3},{"id":4,"title":5,"body":6,"cover":602,"date":603,"description":604,"draft":605,"extension":606,"meta":607,"navigation":166,"path":610,"seo":611,"stem":612,"tags":613,"__hash__":619},"blog\u002Fblog\u002Fplss-api-for-og-lease-databases-geocoding-legal-descriptions-at-scale.md","PLSS API for O&G Lease Databases: Geocoding Legal Descriptions at Scale",{"type":7,"value":8,"toc":596},"minimark",[9,18,23,26,49,52,56,59,66,125,128,539,542,545,549,558,564,568,576,579,592],[10,11,12,13,17],"p",{},"Most oil and gas lease and well databases were built around the legal description, not the coordinate. A lease table has an operator, an effective date, a net-acre figure, and a string like ",[14,15,16],"code",{},"Sec 14, T52N R71W, 6th P.M.",", entered when the lease was acquired. That is enough to write a check and file a form. It is not enough to draw the tract on a map, run a spatial join against a pipeline layer, or hand the data to a Power BI report that expects latitude and longitude. Bridging that gap by hand does not scale past a few dozen records, and it has to be redone every time the table grows. A PLSS API closes the gap programmatically: send the legal descriptions your lease database already stores, get coordinates and boundary geometry back, and run it on whatever schedule the pipeline needs.",[19,20,22],"h2",{"id":21},"what-a-legal-description-api-returns","What a legal-description API returns",[10,24,25],{},"Township America's REST API converts a PLSS legal description to coordinates and back. For each record it returns three things:",[27,28,29,37,43],"ul",{},[30,31,32,36],"li",{},[33,34,35],"strong",{},"Latitude and longitude"," for the described parcel, calculated from official BLM survey data.",[30,38,39,42],{},[33,40,41],{},"A full GeoJSON polygon"," of the actual BLM survey boundary, for the section or quarter-section, not just a centroid point.",[30,44,45,48],{},[33,46,47],{},"Structured section metadata",": the parsed state, principal meridian, township, range, section, and aliquot part.",[10,50,51],{},"Resolution runs across 30+ PLSS states and 37 principal meridians, down to the 1\u002F256 aliquot part, which is about 2.5 acres. That coverage matters for a multi-basin lease book, where the same table can hold Wyoming records on the Sixth Principal Meridian and Oklahoma records on the Indian Meridian without any special handling per state.",[19,53,55],{"id":54},"enriching-a-lease-table-with-the-batch-endpoint","Enriching a lease table with the batch endpoint",[10,57,58],{},"The REST API exposes single lookup, batch, autocomplete, and map tile endpoints, plus Python and TypeScript SDKs and an MCP server for AI agents. For a lease database, the batch endpoint is the one that matters. It accepts up to 100 records per request and returns coordinates and polygon geometry as structured JSON.",[10,60,61,62,65],{},"Read the legal descriptions from your lease table, retain their source IDs locally, and page through them in groups of 100. The legal-location batch endpoint accepts a JSON array of description strings, not objects with an ",[14,63,64],{},"id"," field:",[67,68,73],"pre",{"className":69,"code":70,"language":71,"meta":72,"style":72},"language-json shiki shiki-themes material-theme-lighter github-light github-dark","POST \u002Fbatch\u002Flegal-location\n[\n  \"NENE 14 52N 71W 6th Meridian\",\n  \"SWSW 22 16N 7E Indian Meridian\"\n]\n","json","",[14,74,75,84,91,108,119],{"__ignoreMap":72},[76,77,80],"span",{"class":78,"line":79},"line",1,[76,81,83],{"class":82},"su5hD","POST \u002Fbatch\u002Flegal-location\n",[76,85,87],{"class":78,"line":86},2,[76,88,90],{"class":89},"sP7_E","[\n",[76,92,94,98,102,105],{"class":78,"line":93},3,[76,95,97],{"class":96},"sjJ54","  \"",[76,99,101],{"class":100},"s_sjI","NENE 14 52N 71W 6th Meridian",[76,103,104],{"class":96},"\"",[76,106,107],{"class":89},",\n",[76,109,111,113,116],{"class":78,"line":110},4,[76,112,97],{"class":96},[76,114,115],{"class":100},"SWSW 22 16N 7E Indian Meridian",[76,117,118],{"class":96},"\"\n",[76,120,122],{"class":78,"line":121},5,[76,123,124],{"class":89},"]\n",[10,126,127],{},"The official TypeScript SDK handles the endpoint and response parsing:",[67,129,133],{"className":130,"code":131,"language":132,"meta":72,"style":72},"language-javascript shiki shiki-themes material-theme-lighter github-light github-dark","import { TownshipClient } from 'townshipamerica'\n\nconst client = new TownshipClient({\n  apiKey: process.env.TOWNSHIP_AMERICA_API_KEY,\n})\nconst leases = [\n  { id: 'L-00142', description: 'NENE 14 52N 71W 6th Meridian' },\n  { id: 'L-00143', description: 'SWSW 22 16N 7E Indian Meridian' },\n]\nconst results = await client.batchSearch(leases.map(lease => lease.description))\nfor (const [index, result] of results.entries()) {\n  const lease = leases[index]\n  if (!result) {\n    console.warn('Review unresolved lease:', lease.id, lease.description)\n    continue\n  }\n  console.log(lease.id, result.latitude, result.longitude, result.boundary)\n}\n","javascript",[14,134,135,162,168,194,219,227,240,276,306,311,356,396,415,434,473,479,485,533],{"__ignoreMap":72},[76,136,137,141,144,147,150,153,156,159],{"class":78,"line":79},[76,138,140],{"class":139},"sVHd0","import",[76,142,143],{"class":89}," {",[76,145,146],{"class":82}," TownshipClient",[76,148,149],{"class":89}," }",[76,151,152],{"class":139}," from",[76,154,155],{"class":96}," '",[76,157,158],{"class":100},"townshipamerica",[76,160,161],{"class":96},"'\n",[76,163,164],{"class":78,"line":86},[76,165,167],{"emptyLinePlaceholder":166},true,"\n",[76,169,170,174,178,182,185,188,191],{"class":78,"line":93},[76,171,173],{"class":172},"sbsja","const",[76,175,177],{"class":176},"s_hVV"," client",[76,179,181],{"class":180},"smGrS"," =",[76,183,184],{"class":180}," new",[76,186,146],{"class":187},"sGLFI",[76,189,190],{"class":82},"(",[76,192,193],{"class":89},"{\n",[76,195,196,200,203,206,209,212,214,217],{"class":78,"line":110},[76,197,199],{"class":198},"skxfh","  apiKey",[76,201,202],{"class":89},":",[76,204,205],{"class":82}," process",[76,207,208],{"class":89},".",[76,210,211],{"class":82},"env",[76,213,208],{"class":89},[76,215,216],{"class":176},"TOWNSHIP_AMERICA_API_KEY",[76,218,107],{"class":89},[76,220,221,224],{"class":78,"line":121},[76,222,223],{"class":89},"}",[76,225,226],{"class":82},")\n",[76,228,230,232,235,237],{"class":78,"line":229},6,[76,231,173],{"class":172},[76,233,234],{"class":176}," leases",[76,236,181],{"class":180},[76,238,239],{"class":82}," [\n",[76,241,243,246,249,251,253,256,259,262,265,267,269,271,273],{"class":78,"line":242},7,[76,244,245],{"class":89},"  {",[76,247,248],{"class":198}," id",[76,250,202],{"class":89},[76,252,155],{"class":96},[76,254,255],{"class":100},"L-00142",[76,257,258],{"class":96},"'",[76,260,261],{"class":89},",",[76,263,264],{"class":198}," description",[76,266,202],{"class":89},[76,268,155],{"class":96},[76,270,101],{"class":100},[76,272,258],{"class":96},[76,274,275],{"class":89}," },\n",[76,277,279,281,283,285,287,290,292,294,296,298,300,302,304],{"class":78,"line":278},8,[76,280,245],{"class":89},[76,282,248],{"class":198},[76,284,202],{"class":89},[76,286,155],{"class":96},[76,288,289],{"class":100},"L-00143",[76,291,258],{"class":96},[76,293,261],{"class":89},[76,295,264],{"class":198},[76,297,202],{"class":89},[76,299,155],{"class":96},[76,301,115],{"class":100},[76,303,258],{"class":96},[76,305,275],{"class":89},[76,307,309],{"class":78,"line":308},9,[76,310,124],{"class":82},[76,312,314,316,319,321,324,326,328,331,334,336,339,341,345,348,351,353],{"class":78,"line":313},10,[76,315,173],{"class":172},[76,317,318],{"class":176}," results",[76,320,181],{"class":180},[76,322,323],{"class":139}," await",[76,325,177],{"class":82},[76,327,208],{"class":89},[76,329,330],{"class":187},"batchSearch",[76,332,333],{"class":82},"(leases",[76,335,208],{"class":89},[76,337,338],{"class":187},"map",[76,340,190],{"class":82},[76,342,344],{"class":343},"s99_P","lease",[76,346,347],{"class":172}," =>",[76,349,350],{"class":82}," lease",[76,352,208],{"class":89},[76,354,355],{"class":82},"description))\n",[76,357,359,362,365,367,370,373,375,378,381,384,386,388,391,394],{"class":78,"line":358},11,[76,360,361],{"class":139},"for",[76,363,364],{"class":82}," (",[76,366,173],{"class":172},[76,368,369],{"class":89}," [",[76,371,372],{"class":176},"index",[76,374,261],{"class":89},[76,376,377],{"class":176}," result",[76,379,380],{"class":89},"]",[76,382,383],{"class":180}," of",[76,385,318],{"class":82},[76,387,208],{"class":89},[76,389,390],{"class":187},"entries",[76,392,393],{"class":82},"()) ",[76,395,193],{"class":89},[76,397,399,402,404,406,408,411,413],{"class":78,"line":398},12,[76,400,401],{"class":172},"  const",[76,403,350],{"class":176},[76,405,181],{"class":180},[76,407,234],{"class":82},[76,409,410],{"class":198},"[",[76,412,372],{"class":82},[76,414,124],{"class":198},[76,416,418,421,423,426,429,432],{"class":78,"line":417},13,[76,419,420],{"class":139},"  if",[76,422,364],{"class":198},[76,424,425],{"class":180},"!",[76,427,428],{"class":82},"result",[76,430,431],{"class":198},") ",[76,433,193],{"class":89},[76,435,437,440,442,445,447,449,452,454,456,458,460,462,464,466,468,471],{"class":78,"line":436},14,[76,438,439],{"class":82},"    console",[76,441,208],{"class":89},[76,443,444],{"class":187},"warn",[76,446,190],{"class":198},[76,448,258],{"class":96},[76,450,451],{"class":100},"Review unresolved lease:",[76,453,258],{"class":96},[76,455,261],{"class":89},[76,457,350],{"class":82},[76,459,208],{"class":89},[76,461,64],{"class":82},[76,463,261],{"class":89},[76,465,350],{"class":82},[76,467,208],{"class":89},[76,469,470],{"class":82},"description",[76,472,226],{"class":198},[76,474,476],{"class":78,"line":475},15,[76,477,478],{"class":139},"    continue\n",[76,480,482],{"class":78,"line":481},16,[76,483,484],{"class":89},"  }\n",[76,486,488,491,493,496,498,500,502,504,506,508,510,513,515,517,519,522,524,526,528,531],{"class":78,"line":487},17,[76,489,490],{"class":82},"  console",[76,492,208],{"class":89},[76,494,495],{"class":187},"log",[76,497,190],{"class":198},[76,499,344],{"class":82},[76,501,208],{"class":89},[76,503,64],{"class":82},[76,505,261],{"class":89},[76,507,377],{"class":82},[76,509,208],{"class":89},[76,511,512],{"class":82},"latitude",[76,514,261],{"class":89},[76,516,377],{"class":82},[76,518,208],{"class":89},[76,520,521],{"class":82},"longitude",[76,523,261],{"class":89},[76,525,377],{"class":82},[76,527,208],{"class":89},[76,529,530],{"class":82},"boundary",[76,532,226],{"class":198},[76,534,536],{"class":78,"line":535},18,[76,537,538],{"class":89},"}\n",[10,540,541],{},"Keep IDs in your own source-to-result mapping and check for an unresolved result before updating a row. The SDK returns coordinates and a nullable boundary for each resolved tract, so the integration should distinguish missing geometry from a failed lookup. API request failures need a separate retry path.",[10,543,544],{},"Because lookup does not change the source record, you can re-run it on a schedule. New leases entered this week get geocoded on the next pass. Store the original description, resolved legal location, and lookup date with the geometry so later title corrections can be traced rather than silently overwritten.",[19,546,548],{"id":547},"authentication-rate-limits-and-choosing-a-tier","Authentication, rate limits, and choosing a tier",[10,550,551,552,557],{},"Requests authenticate with an API key, and the batch endpoint is metered per record. The API is sold on three request tiers, Build, Scale, and Enterprise, and the right one depends on how many records you move per month. A land department refreshing a few thousand active leases on a monthly cadence sits at one end; an operator enriching every well and unit across several basins on a nightly job sits at the other. The current per-record pricing and tier limits live on the pricing page, and the ",[553,554,556],"a",{"href":555},"\u002Fguides\u002Fapi-integration","API integration guide"," covers authentication and the exact endpoint reference.",[10,559,560,561,563],{},"One practical constraint shapes the code: the 100-record cap per request. Size your batches to it, add a retry around each batch so a single failed request does not stall the run, and log the ",[14,562,64],{}," values that did not resolve so a person can review odd or incomplete descriptions rather than letting them disappear.",[19,565,567],{"id":566},"from-coordinates-to-a-fully-enriched-lease-record","From coordinates to a fully enriched lease record",[10,569,570,571,575],{},"Coordinates and a polygon are the foundation. For an oil and gas lease book, the next question is usually what sits on or next to each tract, and that is where the ",[553,572,574],{"href":573},"\u002Findustries\u002Foil-and-gas","Energy data pack"," adds the operational layers. Once a lease is geocoded, the Energy pack overlays producing-state wells for Colorado, North Dakota, Oklahoma, Wyoming, and New Mexico, plus federal wells, BLM O&G leases, county-level ONRR federal royalty totals for regional context, the nearest HIFLD pipelines, split-estate detection, and FracFocus disclosures, all on the same PLSS grid. A raw legal description becomes a row that knows where it is, what it looks like as a boundary, and what offset activity surrounds it.",[10,577,578],{},"The build order is what keeps this maintainable. Geocode first, through the REST API, so every record has a stable coordinate and geometry. Layer the Energy pack data on top of those coordinates second. Keeping the two steps separate means your lease database gets its spatial backbone once, and the enrichment layers can change without re-parsing a single legal description.",[10,580,581,582,586,587,591],{},"If your lease or well table still stores tracts only as text, the batch API is the shortest path to coordinates you can actually query, map, and report on. Start with the ",[553,583,585],{"href":584},"\u002Fapi","API reference"," to wire up a first batch, check the ",[553,588,590],{"href":589},"\u002Fpricing","pricing page"," to match a tier to your record volume, and let the enrichment run on the same schedule as the rest of your data.",[593,594,595],"style",{},"html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}",{"title":72,"searchDepth":86,"depth":86,"links":597},[598,599,600,601],{"id":21,"depth":86,"text":22},{"id":54,"depth":86,"text":55},{"id":547,"depth":86,"text":548},{"id":566,"depth":86,"text":567},"\u002Fimages\u002Fblog\u002Fplss-api-for-og-lease-databases-geocoding-legal-descriptions-at-scale\u002Fcover.webp","2026-09-29T10:00:00Z","Use a PLSS API to geocode oil and gas lease database legal descriptions at scale, returning latitude, longitude, and GeoJSON polygons for every tract.",false,"md",{"author":608,"category":609},"Township America","industry","\u002Fblog\u002Fplss-api-for-og-lease-databases-geocoding-legal-descriptions-at-scale",{"title":5,"description":604},"blog\u002Fplss-api-for-og-lease-databases-geocoding-legal-descriptions-at-scale",[614,615,616,617,618],"plss-api","oil-and-gas","geocoding","lease-database","rest-api","NiYnc8Giknx4Vs06IAgJ8680vt6rcxuueZ3cOMXc-j0"]