Build with operational receipts: address validation, geocoding, flood, census, climate, risk signals, MCP tools, x402 payments, and independent verification.
Eligible responses can return a decision-ready verdict and a tamper-evident operational receipt for independent verification.
Customers retain the receipt and associated verification material needed to verify what was returned at decision time, on their own infrastructure, independent of any GeoClear application server.
https://geoclear.io · All responses JSON · All timestamps UTCX-GeoClear-Receipt header on every response. No installs, no Postman. Getting started
Authentication, quickstart, rate limits, and errors. Start here if you're integrating GeoClear for the first time.
Pass your API key via header or query parameter on every request.
curl https://geoclear.io/api/address?street=Main+St&city=Austin&state=TX \
-H "X-Api-Key: YOUR_API_KEY"curl "https://geoclear.io/api/address?street=Main+St&city=Austin&state=TX&key=YOUR_API_KEY"
Verify an address in under a minute.
curl "https://geoclear.io/api/address?number=525&street=Lexington+Ave&city=New+York&state=NY" \ -H "X-Api-Key: YOUR_API_KEY"
const res = await fetch(
'https://geoclear.io/api/address?number=525&street=Lexington+Ave&city=New+York&state=NY',
{ headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
);
const { data } = await res.json();
console.log(data[0].full_address, data[0].confidence);import requests
r = requests.get(
'https://geoclear.io/api/address',
params={'number': '525', 'street': 'Lexington Ave', 'city': 'New York', 'state': 'NY'},
headers={'X-Api-Key': 'YOUR_API_KEY'}
)
data = r.json()['data']
print(data[0]['full_address'], data[0]['confidence']){
"ok": true,
"data": [{
"full_address": "525 Lexington Ave, New York, NY 10017",
"add_number": "525",
"st_name": "Lexington",
"st_pos_typ": "Ave",
"st_pre_dir": "",
"city": "New York",
"state": "NY",
"zip_code": "10017",
"latitude": 40.7556,
"longitude": -73.9729,
"county_fips": "36061",
"timezone": "America/New_York",
"residential": false,
"confidence": 96
}]
}Limits are enforced per API key. Exceeding either limit returns 429 Too Many Requests.
| Tier | Price | Req / min | Req / day |
|---|---|---|---|
| Free | $0 | 10 | 10,000 |
| Starter | $49/mo | 100 | 50,000 |
| Growth | $199/mo | 500 | 150,000 |
| Professional | $499/mo | 1,000 | 500,000 |
| Scale | $999/mo | 9,999 | 5,000,000 |
Rate limit headers are included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
All errors return a JSON body with ok: false and an error string.
Each error includes a machine-readable Resolution so AI agents and SDKs can self-heal without human intervention. Inspect the response error string for context; the table below tells you what to do.
| Status | Meaning | Resolution (for agents + SDKs) |
|---|---|---|
| 400 | Bad request, missing or invalid parameters | Do not retry as-is. Inspect error for the specific field; fix the request payload and re-issue. Validation errors are deterministic, same payload will fail again. |
| 401 | Missing or invalid API key | Verify X-Api-Key header is present and not revoked. For ephemeral / rotated keys, refresh and retry once. Do not retry on consecutive 401s, escalate to operator. |
| 402 | Payment required, premium tool or tier upgrade needed | For x402 callers: read accepts[] in the response body, sign the EIP-712 payment per x402 spec, and retry with the X-Payment header. For subscription callers: upgrade to Pro tier or higher. |
| 429 | Rate limit exceeded (per-minute or per-day) | Honor Retry-After header if present (seconds). Otherwise exponential backoff starting at 1s, doubling, capped at 60s. After 5 retries, surface to operator. Per-day quota resets at 00:00 UTC. |
| 500 | Internal server error | Retry once after 2s with the same payload. If second attempt also returns 500, do not retry further, log the response’s x-request-id header and report at support@geoclear.io. Status: /status. |
{
"ok": false,
"error": "Invalid or revoked API key."
}Core concepts
What a verdict is, what a receipt is, and why offline verification matters. Read these once before integrating, the API surface makes more sense when you know the model.
- What is a location verdict?Signals → verdict → receipt.
- Operational receiptsThe conceptual primer, what a receipt represents, how it travels, how verification works.
- Verified location assetsVerdict, waypoint, geofence, route decision, landing-zone, the asset taxonomy for agent-to-agent location handoffs.
- Independent verificationCustomer-held receipts + verification material for long-term audit.
- Location data vs receiptsWhy a verdict + receipt is different from a field bundle.
- From lookup to instructionWhy agentic systems make location an instruction, and instructions need receipts.
API reference
Address verification, suggest, reverse, bulk, enrichment. Every response can carry an X-GeoClear-Receipt header.
?fuzzy=true for typo-tolerant matching, "Lexingtn Ave" finds "Lexington Ave".
| Parameter | Type | Description | |
|---|---|---|---|
| number | string | optional | House/building number (e.g. "525") |
| street | string | optional | Street name (e.g. "Lexington Ave") |
| city | string | optional | City name |
| state | string | optional | 2-letter state code (e.g. "NY") |
| zip | string | optional | ZIP code |
| fuzzy | boolean | optional | Enable typo-tolerant matching. Default: false |
| limit | integer | optional | Max results. Default: 20, max: 100 |
curl "https://geoclear.io/api/address?number=525&street=Lexington+Ave&state=NY" \
-H "X-Api-Key: YOUR_API_KEY"
# Fuzzy match
curl "https://geoclear.io/api/address?street=Lexingtn+Ave&state=NY&fuzzy=true" \
-H "X-Api-Key: YOUR_API_KEY"const params = new URLSearchParams({ number: '525', street: 'Lexington Ave', state: 'NY' });
const res = await fetch(`https://geoclear.io/api/address?${params}`, {
headers: { 'X-Api-Key': 'YOUR_API_KEY' }
});
const { data } = await res.json();America/New_York)| Parameter | Type | Description | |
|---|---|---|---|
| q | string | required | Address prefix, min 2 characters |
| state | string | optional | Scope to a state (2-letter code) |
| zip | string | optional | Scope to a ZIP code |
| limit | integer | optional | Max results. Default: 10, max: 20 |
curl "https://geoclear.io/api/suggest?q=525+Lex&state=NY&limit=5" \ -H "X-Api-Key: YOUR_API_KEY"
const res = await fetch('https://geoclear.io/api/suggest?q=525+Lex&state=NY', {
headers: { 'X-Api-Key': 'YOUR_API_KEY' }
});
const { data } = await res.json(); // array of address objectscurl -X POST https://geoclear.io/api/address/bulk \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"addresses": [
{ "number": "525", "street": "Lexington Ave", "state": "NY" },
{ "number": "1", "street": "Market St", "state": "CA" }
]
}'const res = await fetch('https://geoclear.io/api/address/bulk', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
addresses: [
{ number: '525', street: 'Lexington Ave', state: 'NY' },
{ number: '1', street: 'Market St', state: 'CA' }
]
})
});
const { results } = await res.json();{
"ok": true,
"results": [
{ "full_address": "525 Lexington Ave, New York, NY 10017", "confidence": 96, "...": "..." },
{ "full_address": "1 Market St, San Francisco, CA 94105", "confidence": 96, "...": "..." }
]
}| Parameter | Type | Description | |
|---|---|---|---|
| lat | number | required | Latitude (decimal degrees) |
| lon | number | required | Longitude (decimal degrees) |
| radius_km | number | optional | Search radius in km. Default: 1.0 |
| limit | integer | optional | Max results. Default: 20, max: 500 |
curl "https://geoclear.io/api/near?lat=40.7556&lon=-73.9729&radius_km=0.5&limit=10" \ -H "X-Api-Key: YOUR_API_KEY"
const res = await fetch('https://geoclear.io/api/near?lat=40.7556&lon=-73.9729&radius_km=0.5', {
headers: { 'X-Api-Key': 'YOUR_API_KEY' }
});
const { data } = await res.json();| Parameter | Type | Description | |
|---|---|---|---|
| lat | number | optional* | Latitude (use with lon) |
| lon | number | optional* | Longitude (use with lat) |
| address_id | string | optional* | Address UUID from a lookup result (alternative to lat/lon) |
* Either lat+lon or address_id is required.
curl "https://geoclear.io/api/enrich?lat=40.7556&lon=-73.9729" \ -H "X-Api-Key: YOUR_API_KEY"
const res = await fetch('https://geoclear.io/api/enrich?lat=40.7556&lon=-73.9729', {
headers: { 'X-Api-Key': 'YOUR_API_KEY' }
});
const { data } = await res.json();{
"ok": true,
"data": {
"census": {
"tract": "009200",
"block_group": "2",
"geoid": "360610092002"
},
"flood": {
"flood_zone": "X",
"sfha": false,
"panel": "3604970057F"
},
"coordinates": {
"latitude": 40.7556,
"longitude": -73.9729
}
}
}curl "https://geoclear.io/api/zip/20500" \ -H "X-Api-Key: YOUR_API_KEY"
const res = await fetch('https://geoclear.io/api/zip/20500', {
headers: { 'X-Api-Key': 'YOUR_API_KEY' }
});
const { data } = await res.json();curl "https://geoclear.io/api/state/TX" \ -H "X-Api-Key: YOUR_API_KEY"
const res = await fetch('https://geoclear.io/api/state/TX', {
headers: { 'X-Api-Key': 'YOUR_API_KEY' }
});
const { data } = await res.json();curl "https://geoclear.io/v1/me" \ -H "X-Api-Key: YOUR_API_KEY"
const res = await fetch('https://geoclear.io/v1/me', {
headers: { 'X-Api-Key': 'YOUR_API_KEY' }
});
const { data } = await res.json();{
"ok": true,
"data": {
"tier": "starter",
"req_per_min": 100,
"req_per_day": 50000,
"usage_today": 1243,
"usage_total": 87241,
"is_active": true
}
}curl -X POST https://geoclear.io/v1/signup \
-H "Content-Type: application/json" \
-d '{ "email": "you@example.com" }'const res = await fetch('https://geoclear.io/v1/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'you@example.com' })
});
const { key } = await res.json();{
"ok": true,
"key": "gc_free_a1b2c3d4..."
}curl https://geoclear.io/api/health
{
"status": "ok",
"addresses": 198657535,
"version": "1.0.0"
}The two most common alternatives, and what's different.
| GeoClear | SmartyStreets | |
|---|---|---|
| Flood zone determination | ✓ Included free | ✗ Not available |
| Census tract (HMDA) | ✓ Included free | ✗ Not available |
| Address validation | ✓ | ✓ |
| Free tier | 10,000 / month | 250 / month |
| Starting price | $49 / month (Starter) | $299 / month |
| Data sources | Authoritative government & public-sector datasets | USPS + proprietary |
smartystreets.com/street-address calls with geoclear.io/api/address?street=&city=&state=. Response shape is similar, see address lookup docs above. Flood zone and census tract are included on all paid plans.
Agents
MCP server, MCP tools, x402 payments, agent error handling. Same signed-receipt contract as the REST API; agents discover, pay, call, and verify offline.
Security
Receipt header, public verification material, sample verifier. The verification recipe customers retain for long-term audit. Receipts are the implementation reference here; the conceptual primer lives under Core Concepts.
- Receipt headerReceipt header on every operational response. Verifiable independently using retained verification material.
- Public verification materialRetained verification material customers fetch and archive alongside receipts. Substrate detail available under NDA at /security/whitepaper.
- Evidence BundlesWhat's in a bundle, file-by-file reference, verification flow, sample downloads.
- Receipt VaultWhat it stores, what to retain, bundle file structure, offline-verify, archive verification material.
- Customer-held verificationThe "outlive the API" thesis, cornerstone explainer.
Verification over Information. Every GeoClear REST API response carries a receipt header, a portable operational receipt your team retains alongside retained verification material. Verification runs locally on your infrastructure using that retained material; GeoClear's application servers do not participate in the verification result.
The receipt attests to what GeoClear returned at what moment. It does not attest to the ground-truth correctness of underlying datasets, if an authoritative source updates, your old receipt is still valid; it records what we returned on the day you asked.
Issuance: issued behind the trust boundary; public verification material is published. Substrate detail and rotation cadence are available in the developer integration guide for approved evaluators, /security/whitepaper (NDA).
Install the public verifier package
npm install @geoclear/verify-receiptVerify, Node.js
const { verifyGeoClearReceipt } = require('@geoclear/verify-receipt');
const claims = await verifyGeoClearReceipt({
receipt, // value of the receipt response header
method: 'GET',
path: '/v1/address?street=...&city=...',
responseBody, // the JSON body you received
});
// Returns the verified payload object.
// Throws if verification fails or retained evidence does not match.Other runtimes
Python, Go, Rust, and other-runtime verifier reference implementations are available in the developer integration guide for approved evaluators, /security/whitepaper (NDA). The verification model is the same across runtimes: customer-held verification material + a standard signature library; no GeoClear server participates in the verification result.
Receipt payload shape
The public docs intentionally show the verification model, not the production receipt schema. Receipt payload fields and their semantics are available in the developer integration guide for approved evaluators, /security/whitepaper (NDA).
Try it in your browser: open the live verifier demo on the security page, or click Search on the homepage demo, you'll see the receipt auto-verify in under 100 ms with a tamper-test button.
For regulated workflows and enterprise audit integrations, reach out: hello@geoclear.io.
Examples
cURL, Node, Python, Go, and the in-browser verifier. The samples above (in the Authentication and Signed Receipts sections) cover the core flows; this section is the index for jumping to a specific runtime.
- cURLHeader + query auth examples (Authentication ↑)
- Node.jsVerify a receipt with @geoclear/verify-receipt.
- Python & other runtimesReference implementations in the developer integration guide (NDA).
- Interactive consoleTry every endpoint live in your browser.
- Browser verifierVerify a live receipt in your browser. Tamper test included.
- Substrate & key-management postureDetailed verification model + retention guidance under NDA.
Go support is on the roadmap; integration-guide tooling for other runtimes is available to qualified evaluators on request.
A GeoClear Evidence Bundle is a customer-held evidence package for verifying a result years later, without calling GeoClear. The bundle contains the operational receipt, retained evidence, verification material, and supporting references needed for later review. Detailed bundle internals (exact file layout, verifier implementation, key-management guidance) are available to qualified evaluators under NDA, see /security/whitepaper.
Bundle contents at a glance
An Evidence Bundle contains the receipt, retained operational evidence, verification material, supporting references, and a self-contained offline verifier. Detailed bundle internals are shared with qualified procurement and security reviewers under NDA, request the developer integration guide.
Verification flow
Open the self-contained offline verifier from the bundle, drop in the bundle files, and the verifier checks the receipt against the retained verification material entirely on your machine. No call to GeoClear required; verification runs locally in your browser.
For a sample bundle you can verify in your browser, see What Is an Evidence Bundle? and the offline verifier. Honesty disclosure (what this proves / does not prove): on the Security page.
Receipt Vault is the productized customer surface for retained operational evidence. It packages every operational receipt into an Evidence Bundle, exposes a list + detail dashboard for retained receipts, and supports per-receipt download for long-lived audit + chargeback investigation. Pro Compliance + Scale + Enterprise tiers.
What Receipt Vault stores
Receipt Vault stores customer-held operational receipt records, retained verification material, and supporting references needed for audit, chargeback review, and long-horizon verification. Detailed retention models and verifier internals are available to qualified procurement and security reviewers under NDA, request the developer integration guide.
What the customer should retain
- The full Evidence Bundle ZIP for every high-stakes verdict (mortgage origination, insurance claim, agentic-commerce settlement).
- A quarterly snapshot of the published verification material (so a 10-year audit doesn’t depend on any single distribution channel being available later).
- The verification material from each bundle (already included in the ZIP, just don’t lose the bundle).
Surfaces
- /vault/payments, payments dashboard (transactional receipts with settlement-pairing view).
GET /v2/vault/payments, list API, paginated, filterable by tx_hash prefix, merchant_id, date, verdict status.GET /v2/vault/payments/:receipt_id/bundle.zip, per-receipt evidence bundle download.- /security/offline-verifier, verify any bundle ZIP locally in your browser.
Public verification material is published redundantly so a verifier can resolve a key for any historical receipt without depending on a single endpoint, and customers retain a copy in their bundle.
Detailed key-distribution, rotation cadence, and publication-channel topology are available in the Security & Verification Whitepaper under NDA.
What this does not promise
Storage durability is a property of redundant publication + customer-held copies, not a guarantee about the future of any specific service. Customers retain the bundle (Receipt Vault, above) so verification does not depend on any single hosted channel remaining available.
GeoClear issues tamper-evident operational receipts for machine decisions. The signed Evidence Bundle is tamper-evident, and verifiers detect modification. GeoClear does not provide legal certification and does not certify the real-world truth of upstream data sources.