Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/thinair-co:thinair-co-intersections-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: ThinAir Geo Intersections API
version: 1.0.0
description: '## Overview
Geocoding, autocomplete, structured search, place IDs, intersections, routing, distance matrix, isochrones, map matching, traffic, weather, and POI search — one API. REST and MCP consume the same ThinAir Geo service layer; this spec describes the REST surface.
## Base URL & authentication
All endpoints live under `https://geo.thinair.co`. Authenticate with a bearer API key:
```bash
curl "https://geo.thinair.co/v1/geocode?text=Pike Place Market Seattle" \
-H "Authorization: Bearer ta_geo_…"
```
## Observability
Every REST response carries a correlation pair (`X-Request-Id` / `X-Trace-Id`), a cache status (`X-Cache: HIT | HIT-EDGE | STALE | MISS | BYPASS`), and a per-stage timing family (`X-Auth-Ms`, `X-Quota-Ms`, `X-Upstream-Ms`, `X-Worker-Ms`, `X-Edge-Ms`, `X-Total-Ms`) — see components.headers for the full surface. Edge-cached lookups answer in single-digit milliseconds at the edge (verifiable via `X-Edge-Ms`); cold geocoding runs through the regional engine.
## Quota
The daily-quota debit is write-behind on all API-key plans, so `X-Quota-Used` / `X-Quota-Remaining` are eventually consistent (typically within ~30 seconds); `GET /v1/quota` is the authoritative synchronous count.
## Enterprise access
`https://geo.thinair.co` is the canonical public API and MCP surface. Azure API Management (APIM) is available as an enterprise access layer — private deployments, custom quota/SLA, VNET/private-link connectivity, subscription keys, and customer-side governance. APIM is an enterprise access layer. It does not own product behavior. All product behavior lives in the shared ThinAir Geo service layer consumed by REST, MCP, and APIM. APIM calls the same service layer (no separate business logic), preserves request/trace ids and ThinAir response shapes, and may add enterprise auth, quota, IP policy, logging, and private networking. Public documentation keeps `https://geo.thinair.co` as the canonical base URL; enterprise base URLs are issued per customer.'
servers:
- url: https://geo.thinair.co
security:
- bearerAuth: []
tags:
- name: Intersections
paths:
/v1/intersection:
post:
summary: Resolve a named cross-street to coordinates
description: Resolve a named intersection (street1 × street2 within a locality/region/country) to a single best coordinate with a confidence score, admin context, and a fleet-safe fallback. The high-confidence tier matches US-metro highway corners; named non-highway streets resolve through the geocoder fallback. Costs 1 quota unit. `POST /v1/intersections/resolve` is a functional alias with the identical contract (retained for compatibility; not separately listed).
tags:
- Intersections
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/IntersectionResolveRequest'
example:
street1: Bellaire Blvd
street2: Chimney Rock Rd
locality: Houston
region: TX
country: US
responses:
'200':
description: 'Resolved intersection (or honest-empty `feature: null` with a coverage warning).'
content:
application/json:
schema:
$ref: '#/components/schemas/IntersectionResolveResponse'
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
X-Trace-Id:
$ref: '#/components/headers/X-Trace-Id'
X-Cache:
$ref: '#/components/headers/X-Cache'
X-Cache-Hit:
$ref: '#/components/headers/X-Cache-Hit'
X-Cache-Tier:
$ref: '#/components/headers/X-Cache-Tier'
X-Edge-Ms:
$ref: '#/components/headers/X-Edge-Ms'
X-Upstream-Ms:
$ref: '#/components/headers/X-Upstream-Ms'
X-Worker-Ms:
$ref: '#/components/headers/X-Worker-Ms'
X-Total-Ms:
$ref: '#/components/headers/X-Total-Ms'
X-Auth-Ms:
$ref: '#/components/headers/X-Auth-Ms'
X-Quota-Ms:
$ref: '#/components/headers/X-Quota-Ms'
X-Quota-Cost:
$ref: '#/components/headers/X-Quota-Cost'
X-Quota-Used:
$ref: '#/components/headers/X-Quota-Used'
X-Quota-Remaining:
$ref: '#/components/headers/X-Quota-Remaining'
X-Quota-Reset:
$ref: '#/components/headers/X-Quota-Reset'
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-Session-Id:
$ref: '#/components/headers/X-Session-Id'
X-Edge-Location:
$ref: '#/components/headers/X-Edge-Location'
X-Data-Age-S:
$ref: '#/components/headers/X-Data-Age-S'
'400':
description: Invalid request body.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
'429':
description: Quota exceeded for this tenant.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
'502':
description: Upstream geocoder unavailable.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
operationId: postV1Intersection
x-operation-id-source: derived
/v1/intersections/search:
post:
summary: Search for street intersections
description: Search for street-intersection candidates from a free-text cross-street query, scoped by optional locality/region/country. Returns ranked candidates plus a GeoJSON FeatureCollection. Costs 1 quota unit.
tags:
- Intersections
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/IntersectionSearchRequest'
example:
text: Bellaire Blvd and Chimney Rock Rd
locality: Houston
region: TX
country: US
responses:
'200':
description: Intersection search results.
content:
application/json:
schema:
$ref: '#/components/schemas/IntersectionSearchResponse'
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
X-Trace-Id:
$ref: '#/components/headers/X-Trace-Id'
X-Cache:
$ref: '#/components/headers/X-Cache'
X-Cache-Hit:
$ref: '#/components/headers/X-Cache-Hit'
X-Cache-Tier:
$ref: '#/components/headers/X-Cache-Tier'
X-Edge-Ms:
$ref: '#/components/headers/X-Edge-Ms'
X-Upstream-Ms:
$ref: '#/components/headers/X-Upstream-Ms'
X-Worker-Ms:
$ref: '#/components/headers/X-Worker-Ms'
X-Total-Ms:
$ref: '#/components/headers/X-Total-Ms'
X-Auth-Ms:
$ref: '#/components/headers/X-Auth-Ms'
X-Quota-Ms:
$ref: '#/components/headers/X-Quota-Ms'
X-Quota-Cost:
$ref: '#/components/headers/X-Quota-Cost'
X-Quota-Used:
$ref: '#/components/headers/X-Quota-Used'
X-Quota-Remaining:
$ref: '#/components/headers/X-Quota-Remaining'
X-Quota-Reset:
$ref: '#/components/headers/X-Quota-Reset'
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-Session-Id:
$ref: '#/components/headers/X-Session-Id'
X-Edge-Location:
$ref: '#/components/headers/X-Edge-Location'
X-Data-Age-S:
$ref: '#/components/headers/X-Data-Age-S'
'400':
description: Invalid request body.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
'429':
description: Quota exceeded for this tenant.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
'502':
description: Upstream geocoder unavailable.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
operationId: postV1IntersectionsSearch
x-operation-id-source: derived
components:
headers:
X-Quota-Cost:
description: Capability units this call debited.
schema:
type: string
X-Worker-Ms:
description: 'Worker-side overhead: total minus upstream (ms). Decomposes into X-Auth-Ms + X-Quota-Ms + unattributed residue (serialization, telemetry, routing).'
schema:
type: string
X-Edge-Location:
description: Edge location (IATA airport code) that served the request. Omitted when unavailable.
schema:
type: string
X-RateLimit-Limit:
description: Plan cap proxy (-1 = unlimited).
schema:
type: string
X-Session-Id:
description: Session correlation id grouping requests issued under one client session.
schema:
type: string
X-Quota-Reset:
description: ISO-8601 instant the daily counter rolls over.
schema:
type: string
X-Cache-Hit:
description: Legacy boolean cache signal (true|false). Prefer X-Cache.
schema:
type: string
X-Trace-Id:
description: Alias of X-Request-Id for tracing tooling that auto-detects the Trace-Id spelling.
schema:
type: string
X-Data-Age-S:
description: Age in seconds of the underlying data snapshot backing the response (e.g. a traffic observation). Only present on endpoints where data age is meaningful.
schema:
type: string
X-Total-Ms:
description: Equal to X-Edge-Ms; kept distinct per spec §6.
schema:
type: string
X-Quota-Remaining:
description: Daily limit minus used (-1 = unlimited). Eventually consistent (see X-Quota-Used); GET /v1/quota is authoritative.
schema:
type: string
X-Quota-Ms:
description: Synchronous quota work on the request path (ms). All API-key plans use a write-behind debit, so this reflects only the fast synchronous exhausted-flag check. The demo (Try-It) identity keeps the synchronous pre-flight peek + post-success debit (QuotaCounter round-trips).
schema:
type: string
X-Edge-Ms:
description: Total wall time the worker held the request (ms).
schema:
type: string
X-Quota-Used:
description: 'Units consumed in the current daily period. The debit is write-behind on all API-key plans: this value is eventually consistent (typically within ~30 seconds); GET /v1/quota is the authoritative synchronous count.'
schema:
type: string
X-RateLimit-Remaining:
description: Remaining headroom (-1 = unlimited).
schema:
type: string
X-Auth-Ms:
description: API-key validation time (ms). Present only on the ta_* api-key and demo-token paths; OAuth-JWT validation happens inside the auth library and is not measurable.
schema:
type: string
X-Request-Id:
description: Edge-generated request correlation id (req_*).
schema:
type: string
X-Cache:
description: 'Cache status: HIT (served from the cache without an upstream call), HIT-EDGE (served from the edge tier, no durable-store round-trip), STALE (served past its soft TTL while a background refresh runs), MISS (cacheable, went upstream), BYPASS (endpoint has no cache).'
schema:
type: string
enum:
- HIT
- HIT-EDGE
- STALE
- MISS
- BYPASS
X-Cache-Tier:
description: 'Serving cache tier, when reported: edge (edge tier), l0 (in-region cache), or kv (durable edge store).'
schema:
type: string
enum:
- edge
- l0
- kv
X-Upstream-Ms:
description: Wall time spent in engine round-trips (ms). Omitted on cache hits (no upstream call).
schema:
type: string
schemas:
IntersectionSearchResponse:
type: object
properties:
features:
type: array
items:
$ref: '#/components/schemas/IntersectionSearchFeature'
meta:
$ref: '#/components/schemas/IntersectionSearchMeta'
geojson:
$ref: '#/components/schemas/IntersectionSearchFeatureCollection'
warnings:
type: array
items:
type: string
upstream_error:
type:
- string
- 'null'
required:
- features
- meta
- geojson
IntersectionSearchRequest:
type: object
properties:
text:
type: string
minLength: 1
maxLength: 2000
description: Free-text intersection query (e.g. 'Broadway and 42nd Street').
example: Bellaire Blvd and Chimney Rock Rd
locality:
type: string
maxLength: 2000
description: City / town hint.
example: Houston
region:
type: string
maxLength: 2000
description: State / province hint.
example: TX
country:
type: string
minLength: 2
maxLength: 3
description: ISO 3166-1 alpha-2/alpha-3 country code to scope results.
example: US
size:
type: integer
minimum: 1
maximum: 40
description: Maximum candidates to return (1–40). Defaults to 5 in the service layer.
example: 5
required:
- text
description: Search for intersection candidates from a free-text cross-street query.
ProblemDetails:
type: object
properties:
type:
type: string
format: uri
title:
type: string
status:
type: integer
detail:
type: string
code:
type: string
description: Stable internal_code; see /docs/errors
request_id:
type: string
instance:
type: string
retry_after_ms:
type: integer
upgrade_url:
type: string
description: Present on 429 (quota exceeded) and on 401 TRIAL_EXPIRED. Preselects the recommended plan and, when the caller's tenant is known, carries a short-lived token that upgrades the API key you are already using — no key swap and no config change after payment.
suggested_upgrade:
type:
- string
- 'null'
description: Recommended next plan, or null on the top self-serve tier. 429 only.
upgrade_cta:
type: string
description: One-line upgrade prompt. 429 only.
upgrade_plans:
type: array
items:
$ref: '#/components/schemas/UpgradePlan'
description: Full self-serve plan menu. 429 only.
next_step:
type: string
description: Prose instruction naming the same URL as upgrade_url. 429 only.
usage:
type: object
properties:
plan:
type: string
used:
type: number
limit:
type: number
period:
type: string
reset:
type: string
description: ISO 8601 instant the counter rolls over.
required:
- plan
description: Where the cap stands. 429 only; counters are omitted when the denial has none.
expired_at:
type: string
description: ISO 8601 instant the key stopped authenticating. TRIAL_EXPIRED only.
plan:
type: string
description: Plan the expired key carried. TRIAL_EXPIRED only.
quota:
type: object
properties:
daily:
type: number
period:
type: string
required:
- daily
- period
description: Daily allowance the expired key had; -1 = unlimited. TRIAL_EXPIRED only.
required:
- type
- title
- status
- detail
- code
- request_id
- instance
description: RFC 7807 problem-details with ThinAir extensions (code, request_id, retry_after_ms). A 429 additionally carries upgrade_url, suggested_upgrade, upgrade_cta, upgrade_plans, next_step and usage; a 401 TRIAL_EXPIRED carries upgrade_url, expired_at, plan and quota.
UpgradePlan:
type: object
properties:
name:
type: string
price:
type: string
description: Display price, e.g. "$29/mo" or "custom".
quota:
type: string
description: Display allowance, e.g. "10,000/day".
note:
type: string
upgrade_url:
type: string
description: Checkout link for this specific plan. Carries the same plan preselect, in-place upgrade token and src attribution as the top-level upgrade_url.
required:
- name
- price
- quota
- upgrade_url
description: One self-serve plan offered on a 429.
IntersectionSearchFeature:
type: object
properties:
id:
type: string
description: Stable public ThinAir id (`ta_intersection_<key>` / `ta_place_<key>`). Resolvable via `GET /v1/place`.
example: ta_intersection_b3a9f27e61c04d58
name:
type: string
label:
type: string
confidence:
type: number
layer:
type: string
intersection_type:
type: string
enum:
- corner
- interchange
intersection_precision:
type: string
enum:
- geometric_crossing
- tangent_intersection
- centroid_cluster
- approximate
street_kind:
type: string
enum:
- street
- route
cross_street_kind:
type: string
enum:
- street
- route
street_route:
type: string
minLength: 1
maxLength: 128
cross_street_route:
type: string
minLength: 1
maxLength: 128
place_type:
type: string
method:
type: string
lat:
type: number
lon:
type: number
required:
- place_type
- method
- lat
- lon
IntersectionResolveResponse:
type: object
properties:
feature:
$ref: '#/components/schemas/IntersectionResolvedFeature'
confidence:
type: number
description: Resolved feature's confidence (0–1); 0 when unresolved.
fallback_used:
type: boolean
description: True when the geocoder fallback produced the answer (CSV missed or was below threshold).
admin:
type: object
properties:
locality:
type: string
region:
type: string
country:
type: string
description: Admin context echoed back.
meta:
type: object
properties:
upstream_ms:
type: number
method:
type: string
query:
type: string
required:
- upstream_ms
- method
- query
description: Resolution metadata; `method` is the rung that resolved (csv_intersection | intersection | none).
warnings:
type: array
items:
type: string
description: Advisory strings — present on a miss (coverage hint) or geocoder suppress signals.
upstream_error:
type:
- string
- 'null'
precision:
allOf:
- $ref: '#/components/schemas/PrecisionBlock'
- description: Learning-overlay precision adjudication. Present only when the flag-gated overlay applied to this resolution. Omitted otherwise — legacy consumers see no shape change.
required:
- feature
- confidence
- fallback_used
- admin
- meta
IntersectionResolveRequest:
type: object
properties:
street1:
type: string
minLength: 1
maxLength: 2000
description: First street of the cross-street pair.
example: Bellaire Blvd
street2:
type: string
minLength: 1
maxLength: 2000
description: Second (cross) street of the pair.
example: Chimney Rock Rd
locality:
type: string
maxLength: 2000
description: City / town that scopes the lookup.
example: Houston
region:
type: string
maxLength: 2000
description: State / province (full name or abbreviation, e.g. 'TX').
example: TX
country:
type: string
minLength: 2
maxLength: 3
description: ISO 3166-1 alpha-2/alpha-3 country code to scope results.
example: US
confidence_threshold:
type: number
minimum: 0
maximum: 1
description: Confidence floor (0–1) below which a CSV/geocoder hit falls through to the next resolution rung. Defaults to 0.5.
example: 0.5
required:
- street1
- street2
description: Resolve a named cross-street to coordinates. The high-confidence tier (CSV) is US highways only; named non-highway streets resolve via the geocoder fallback (global, lower-confidence). For free-form streets use /v1/geocode.
IntersectionSearchMeta:
type: object
properties:
upstream_ms:
type: number
feature_count:
type: number
cacheHit:
type: boolean
bbox:
type: array
prefixItems:
- type: number
- type: number
- type: number
- type: number
query:
type: string
mode:
type: string
enum:
- geocode
- reverse
required:
- upstream_ms
- feature_count
- query
- mode
IntersectionResolvedFeature:
type:
- object
- 'null'
properties:
id:
type: string
description: Stable public ThinAir id (`ta_intersection_<key>` when the resolved doc carries the derivation inputs, else `ta_place_<key>`). Resolvable via `GET /v1/place`.
example: ta_intersection_b3a9f27e61c04d58
name:
type: string
label:
type: string
confidence:
type: number
layer:
type: string
intersection_type:
type: string
enum:
- corner
- interchange
intersection_precision:
type: string
enum:
- geometric_crossing
- tangent_intersection
- centroid_cluster
- approximate
street_kind:
type: string
enum:
- street
- route
cross_street_kind:
type: string
enum:
- street
- route
street_route:
type: string
minLength: 1
maxLength: 128
cross_street_route:
type: string
minLength: 1
maxLength: 128
place_type:
type: string
method:
type: string
lat:
type: number
lon:
type: number
required:
- place_type
- method
- lat
- lon
description: Best resolved intersection feature, or null when nothing resolved.
PrecisionBlock:
type: object
properties:
class:
type: string
example: intersection
risk_flags:
type: array
items:
type: string
example:
- ambiguous_without_context
required_context:
type: array
items:
type: string
example:
- borough
learning_overlay:
type: object
properties:
applied:
type: boolean
rule_ids:
type: array
items:
type: string
actions:
type: array
items:
type: string
required:
- applied
required:
- class
- risk_flags
- required_context
- learning_overlay
description: Learning-overlay precision adjudication. Present only when the overlay evaluated this query (intersection-class). Omitted otherwise — legacy consumers see no shape change.
IntersectionSearchFeatureCollection:
type: object
properties:
type:
type: string
enum:
- FeatureCollection
features:
type: array
items:
type: object
properties:
type:
type: string
enum:
- Feature
geometry:
type: object
properties:
type:
type: string
enum:
- Point
coordinates:
type: array
prefixItems:
- type: number
- type: number
required:
- type
- coordinates
properties:
type: object
additionalProperties: {}
required:
- type
- geometry
- properties
required:
- type
- features
securitySchemes:
bearerAuth:
type: http
scheme: bearer