API Troubleshooting & Best Practices
Fix common Township Canada API errors including Forbidden responses, CORS issues, rate limiting, and empty results. Includes debugging tips and integration patterns.
Getting errors from the Township Canada API? This guide covers the most common issues developers run into — authentication failures, CORS blocks, rate limits, and unexpected empty responses — with clear fixes for each one.
Common errors and what they mean
Forbidden (HTTP 403)
{ "message": "Forbidden" }
Cause: Your API key is missing, invalid, or not included correctly.
Fix:
- Confirm your API key exists: go to My Account → API Access
- Include it in the
X-API-Keyheader (not as a URL parameter) - Test with curl:
curl -H "X-API-Key: YOUR_KEY" \
"https://developer.townshipcanada.com/search/legal-location?q=SW-25-24-1-W5"
If you get a valid JSON response, your key works. If you still get Forbidden, the key may have been rotated — generate a new one from your account page.
Too Many Requests (HTTP 429)
Cause: You exceeded the rate limit for your API tier.
| Tier | Rate Limit |
|---|---|
| Build | 1 request/second |
| Scale | 5 requests/second |
| Enterprise | 25 requests/second |
Fix:
- Add a delay between requests:
await new Promise(r => setTimeout(r, 1000))in JavaScript, ortime.sleep(1)in Python - Use the Batch API instead of looping single calls — it processes up to 100 records per request
- If you consistently need higher throughput, contact us about upgrading your tier
CORS Policy Error
Access to fetch at 'https://developer.townshipcanada.com/...' has been blocked by CORS policy
Cause: You are calling the API directly from a browser (client-side JavaScript). The API is designed for server-to-server calls and does not include CORS headers by default.
Fix options:
- Proxy through your backend — Make the API call from your server (Node.js, Python, etc.) and return the result to your frontend
- Contact us — If you need direct browser access, we can add your domain to the CORS allowlist
Empty Response (no features)
The API returns a valid HTTP 200 response, but the result contains no features or coordinates.
Possible causes:
- The legal description does not exist (e.g., a township/range combination that was never surveyed)
- The description is at a resolution not supported for that region
- Format is slightly wrong — the API is stricter than the web app
Debugging steps:
- Try the same description in the web app search box — does it work there?
- Check that you included the full meridian (e.g.,
W5not just5) - Verify component ranges: LSD 1–16, Section 1–36, Township 1–126, Range 1–34
- Check the Coverage Guide for resolution limits by region
Database Errors (28000, 08006)
Errors with codes like 28000 or 08006 indicate a service disruption, not an issue with your code.
What to do:
- Check the status page for incident reports
- Wait a few minutes and retry
- If the issue persists beyond 15 minutes, contact us
API key setup
Quick recap of key setup (see the full API key management guide for details):
- Find your key: My Account → API Access
- Include in requests: Add the
X-API-Keyheader to every request - Test before coding: Use curl or Postman to confirm the key works
- Name your keys: Use descriptive names like "production-backend" or "staging-test" to keep track of which key is used where
- Rotate regularly: Generate new keys periodically and phase out old ones
Rate limiting best practices
Add delay between requests
// JavaScript — simple delay
for (const query of queries) {
const result = await fetch(url + query, { headers });
await new Promise((r) => setTimeout(r, 1000));
}
# Python — simple delay
import time
for query in queries:
result = requests.get(url + query, headers=headers)
time.sleep(1)
Use exponential backoff on 429
async function fetchWithBackoff(url, headers, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const res = await fetch(url, { headers });
if (res.status !== 429) return res;
await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, i)));
}
throw new Error("Rate limit exceeded after retries");
}
Use the Batch API for bulk work
Instead of looping 1,000 single calls (which takes 17+ minutes at 1/sec), use the Batch API to process 100 records per call — the same 1,000 records take 10 calls.
See the Batch API Guide for chunking examples in Node.js and Python.
Format differences: web app vs. API
The web app's search box is more forgiving than the API:
| Issue | Web App | API |
|---|---|---|
| Missing "W" on meridian | May auto-correct | Returns empty |
| Extra spaces | Handled | May cause issues |
| Mixed case | Handled | Handled |
| Partial descriptions | Shows suggestions | Returns empty |
When building API integrations, always normalize your input first:
- Include dashes between all components
- Add the "W" prefix on meridians
- Remove extra text, parentheses, and place names
- Trim whitespace
Integration patterns
Caching
If your application looks up the same legal descriptions repeatedly, cache the results. Legal land descriptions map to fixed coordinates — the result for SW-25-24-1-W5 will not change.
Error handling
Always handle these response codes:
- 200 — Success, parse the result
- 400 — Bad request, check your input format
- 403 — Authentication failed, check your API key
- 429 — Rate limited, wait and retry
- 500/502/503 — Server issue, retry after a short delay
OpenAPI spec
Download the OpenAPI specification at /openapi.yaml and import it into Postman, Swagger UI, or Insomnia for interactive testing and documentation.
Related guides
- API Integration Guide — getting started with the API
- API Key Management — creating and managing API keys
- Search API Guide — single-location lookups
- Batch API Guide — bulk conversions
- Coverage & Limitations — what regions and resolutions are supported
Related Guides
Legal Land Description API Integration Guide
Integrate legal land description APIs into your applications. Convert LLDs to coordinates, add autocomplete search, process batch records, and display DLS/NTS grid maps. REST API with JSON responses.
Managing API Keys for Development, Staging, and Production
Create and manage multiple Township Canada API keys for different environments. Naming conventions, key rotation, environment variables, and CI/CD setup.
Building Autocomplete Search with the Township Canada API
Build a search-as-you-type component for legal land descriptions using the Township Canada Autocomplete API. Includes debouncing, proximity biasing, and examples in vanilla JS and React.