Official TypeScript SDK for the Township Canada API — convert Canadian legal land descriptions (DLS, NTS, Geographic Townships) to GPS coordinates and back.
Documentation · GitHub · npm
npm install townshipcanada
# or
pnpm add townshipcanada
# or
yarn add townshipcanadaimport { TownshipClient } from "townshipcanada";
const client = new TownshipClient({
apiKey: "your-api-key" // Get yours at https://townshipcanada.com/api
});
// Convert a legal land description to GPS coordinates
const result = await client.search("NW-36-42-3-W5");
console.log(result.latitude); // 52.123456
console.log(result.longitude); // -114.654321
console.log(result.province); // "Alberta"- Sign up at townshipcanada.com/api
- Create an API key from your dashboard
- Pass it to the client constructor
const client = new TownshipClient({ apiKey: process.env.TOWNSHIP_API_KEY! });Create a new client instance.
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
required | Your Township Canada API key |
baseUrl |
string |
https://developer.townshipcanada.com |
API base URL |
timeout |
number |
30000 |
Request timeout in ms |
fetch |
function |
globalThis.fetch |
Custom fetch implementation |
Convert a legal land description to GPS coordinates.
const result = await client.search("NW-36-42-3-W5");
// DLS (Dominion Land Survey) — Alberta, Saskatchewan, Manitoba
await client.search("NW-36-42-3-W5"); // Quarter section
await client.search("10-36-42-3-W5"); // LSD (Legal Subdivision)
await client.search("36-42-3-W5"); // Section
// NTS (National Topographic System) — British Columbia
await client.search("A-2-F/93-P-8"); // Quarter Unit
await client.search("2-F/93-P-8"); // Unit
// Geographic Townships — Ontario
await client.search("Lot 2 Con 4 Osprey");Returns: SearchResult
{
legalLocation: string // "NW-36-42-3-W5"
latitude: number // 52.123456
longitude: number // -114.654321
province: string // "Alberta"
surveySystem: SurveySystem // "DLS"
unit: Unit // "Quarter Section"
boundary: GeoJSONPolygon | GeoJSONMultiPolygon | null
raw: LocationFeature[] // Raw GeoJSON features
}Find the legal land description for a GPS coordinate.
const result = await client.reverse(-114.654, 52.123);
console.log(result.legalLocation); // "NW-36-42-3-W5"
// With options
const result = await client.reverse(-114.654, 52.123, {
surveySystem: "DLS",
unit: "Quarter Section"
});Options:
| Option | Type | Description |
|---|---|---|
surveySystem |
SurveySystem |
Filter by survey system |
unit |
Unit |
Resolution (e.g. "LSD", "Quarter Section") |
Returns: SearchResult (same shape as search)
Get autocomplete suggestions for a partial legal land description.
const suggestions = await client.autocomplete("NW-25-24");
for (const s of suggestions) {
console.log(s.legalLocation); // "NW-25-24-1-W5"
console.log(s.latitude, s.longitude);
}
// With options
const suggestions = await client.autocomplete("NW-25", {
limit: 5,
proximity: [-114.0, 51.0] // [longitude, latitude]
});Options:
| Option | Type | Default | Description |
|---|---|---|---|
limit |
number |
3 |
Number of results (1-10) |
proximity |
[longitude, latitude] |
— | Bias results toward a point |
Returns: AutocompleteSuggestion[]
{
legalLocation: string; // "NW-25-24-1-W5"
latitude: number; // 51.077932
longitude: number; // -114.01924
surveySystem: SurveySystem; // "DLS"
unit: Unit; // "Quarter Section"
}Convert multiple legal land descriptions at once. Automatically handles chunking for large batches (API max: 100 per request).
const result = await client.batchSearch([
"NW-36-42-3-W5",
"SE-1-50-10-W4",
"A-2-F/93-P-8",
"NE-12-25-1-W2"
]);
console.log(result.success); // 4
console.log(result.failed); // 0
console.log(result.results); // SearchResult[]
// Process results
for (const item of result.results) {
console.log(`${item.legalLocation}: ${item.latitude}, ${item.longitude}`);
}Options:
| Option | Type | Default | Description |
|---|---|---|---|
chunkSize |
number |
100 |
Records per API request |
Returns: BatchResult
{
results: SearchResult[] // Successfully converted items
total: number // Total items submitted
success: number // Successful conversions
failed: number // Failed conversions
}Reverse geocode multiple coordinate pairs at once.
const result = await client.batchReverse([
[-114.654, 52.123], // [longitude, latitude]
[-114.072, 51.045],
[-110.456, 50.321]
]);
for (const item of result.results) {
console.log(`${item.longitude},${item.latitude} => ${item.legalLocation}`);
}Options:
| Option | Type | Default | Description |
|---|---|---|---|
chunkSize |
number |
100 |
Records per API request |
surveySystem |
SurveySystem |
— | Filter by survey system |
unit |
Unit |
— | Resolution unit |
Get the boundary polygon for a legal land description.
const boundary = await client.boundary("NW-36-42-3-W5");
if (boundary) {
console.log(boundary.type); // "Polygon"
console.log(boundary.coordinates); // [[[lng, lat], ...]]
}Returns: GeoJSONPolygon | GeoJSONMultiPolygon | null
Get the raw GeoJSON FeatureCollection from the API. Useful when you need full control over the response.
const featureCollection = await client.raw("NW-36-42-3-W5");
console.log(featureCollection.type); // "FeatureCollection"
console.log(featureCollection.features); // LocationFeature[]The SDK throws typed errors that you can catch and handle:
import {
TownshipClient,
AuthenticationError,
NotFoundError,
RateLimitError,
ValidationError,
PayloadTooLargeError,
TownshipError
} from "townshipcanada";
try {
const result = await client.search("INVALID");
} catch (error) {
if (error instanceof AuthenticationError) {
// 401 — invalid or missing API key
} else if (error instanceof NotFoundError) {
// 404 — location not found
} else if (error instanceof RateLimitError) {
// 429 — too many requests
} else if (error instanceof ValidationError) {
// 400 — malformed request
} else if (error instanceof PayloadTooLargeError) {
// 413 — batch exceeds 100 records
} else if (error instanceof TownshipError) {
// Other API errors
console.error(error.message, error.statusCode);
}
}Full type definitions are included and exported. All types are available for import:
import type {
SearchResult,
BatchResult,
AutocompleteSuggestion,
SurveySystem,
Unit,
GeoJSONPolygon,
LocationFeature
} from "townshipcanada";| System | Provinces | Format Examples |
|---|---|---|
| DLS (Dominion Land Survey) | AB, SK, MB | NW-36-42-3-W5, 10-36-42-3-W5 |
| NTS (National Topographic System) | BC | A-2-F/93-P-8, 2-F/93-P-8 |
| GTS (Geographic Townships) | ON | Lot 2 Con 4 Osprey |
- Node.js 18+ (uses native
fetch) - Works in browsers, Deno, Bun, Cloudflare Workers, and any environment with
fetch
MIT - Maps & Apps Inc.