Skip to main content
POST
/
v1
/
ai
/
query
curl --request POST \ --url https://api.footstep.ai/v1/ai/query \ --header 'Content-Type: application/json' \ --header 'x-api-key: <api-key>' \ --data ' { "query": "Walking route from Kings Cross to Tower Bridge" } '
{
  "intent": "route",
  "parameters": {},
  "result": {},
  "summary": "<string>"
}
Send a natural language query and get back structured geospatial results. The endpoint figures out what you’re asking for (directions, a location, reachability, etc.), resolves any text locations to coordinates, calls the appropriate backend, and returns the full result.

How intent is classified

The endpoint maps queries to the backend that best fits:
Your query sounds like…IntentBackend called
”Directions from A to B”route/v1/routing/route
”Best order to visit these stops”optimize/v1/routing/optimize
”How far can I walk in 30 minutes”isochrone/v1/routing/isochrone
”What’s the elevation at…”elevation/v1/routing/elevation
”Distance between A, B, and C”matrix/v1/routing/matrix
”Where is…” / “Find…”geocode/v1/geocoding/search
”What’s at these coordinates”reverse_geocode/v1/geocoding/reverse

Using context

Pass context.location when your query uses relative terms like “nearest”, “nearby”, or “from here”. Without it, the endpoint can’t resolve those references. Pass context.country to disambiguate place names. “Springfield” with country: "GBR" resolves differently than with country: "USA".
{
  "query": "Walking directions to the nearest park",
  "context": {
    "location": { "lat": 51.5322, "lon": -0.1240 },
    "country": "GBR"
  }
}

Response structure

The response always includes:
FieldWhat it contains
intentWhat the query was classified as (route, geocode, isochrone, etc.)
parametersThe parameters inferred from the query and passed to the backend
resultThe full backend response (same schema as calling the endpoint directly)
summaryA natural language summary of the result
The result field contains the exact same response you’d get calling the backend endpoint directly. If the intent is route, result contains a RouteResponse. If geocode, it contains a GeocodingSearchResponse. No new schemas to learn.

Error handling

If the query is ambiguous or can’t be resolved:
{
  "error": "ambiguous_query",
  "message": "Could not determine a specific intent from your query.",
  "suggestions": [
    "Try: 'Directions from A to B'",
    "Try: 'Where is [place name]?'",
    "Try: 'How far can I drive in 30 minutes from [location]?'"
  ]
}
If a location in the query can’t be geocoded, the response includes what was resolved and what failed:
{
  "error": "geocode_failed",
  "message": "Could not find a location matching 'the old pub near the river'.",
  "partial": {
    "intent": "route",
    "resolved_locations": [
      { "text": "Kings Cross", "resolved": { "lat": 51.53, "lon": -0.12 } }
    ],
    "unresolved_locations": [
      { "text": "the old pub near the river" }
    ]
  }
}

Authorizations

x-api-key
string
header
required

Your Footstep API key

Body

application/json
query
string
required

Natural language query (e.g. 'Walking route from Kings Cross to Tower Bridge', 'Where is Buckingham Palace?', 'How far can I drive in 30 minutes from Liverpool Street?')

Maximum string length: 1000
context
object

Optional context to improve query understanding

Response

Structured result from the resolved query

intent
enum<string>
required

Classified intent of the query

Available options:
route,
optimize,
isochrone,
elevation,
matrix,
geocode,
reverse_geocode
parameters
object
required

Parameters inferred from the query and passed to the backend endpoint

result
object
required

Full response from the backend endpoint (RouteResponse, GeocodingSearchResponse, IsochroneResponse, etc.)

summary
string
required

Natural language summary of the result