{
  "openapi": "3.1.0",
  "info": {
    "title": "Tokenbooth Location Grounding API",
    "version": "2026-08-05",
    "description": "A paid x402 service that turns messy location clues into structured place data. One request resolves one location."
  },
  "servers": [
    {
      "url": "https://tools.tokenbooth.io",
      "description": "Production API"
    }
  ],
  "paths": {
    "/v1/location/resolve": {
      "post": {
        "operationId": "resolveLocation",
        "summary": "Resolve one location clue into structured place data",
        "description": "If the request is location-related and no payment is attached, the service returns 402 with a PAYMENT-REQUIRED x402 challenge. Sign one advertised option and retry the same request with PAYMENT-SIGNATURE.",
        "tags": [
          "Location grounding"
        ],
        "parameters": [
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "Signed x402 payment payload used on the paid retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-REQUEST-ID",
            "in": "header",
            "required": false,
            "description": "Optional caller-supplied request identifier for correlation.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LocationResolutionRequest"
              },
              "examples": {
                "cloudGate": {
                  "summary": "Landmark nickname with city hints",
                  "value": {
                    "locationDetails": "the bean in chicago",
                    "hints": {
                      "city": "Chicago",
                      "countryCode": "US",
                      "near": "Millennium Park"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Paid location resolution response.",
            "headers": {
              "PAYMENT-RESPONSE": {
                "description": "x402 settlement response for the completed payment.",
                "schema": {
                  "type": "string"
                }
              },
              "X-REQUEST-ID": {
                "description": "Server correlation identifier.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResolutionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request JSON or schema.",
            "headers": {
              "X-REQUEST-ID": {
                "description": "Server correlation identifier.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalidRequest": {
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Request body must be a single location resolution object."
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required. Read the PAYMENT-REQUIRED header, sign one advertised x402 payment option, and retry the same request with PAYMENT-SIGNATURE.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "x402 payment challenge. This is the source of truth for current payment options and amount.",
                "required": true,
                "schema": {
                  "type": "string"
                }
              },
              "X-REQUEST-ID": {
                "description": "Server correlation identifier.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "The request is not location-related and cannot be serviced.",
            "headers": {
              "X-REQUEST-ID": {
                "description": "Server correlation identifier.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "cannotService": {
                    "value": {
                      "error": {
                        "code": "cannot_service",
                        "message": "This service only resolves location-related requests."
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "headers": {
              "X-REQUEST-ID": {
                "description": "Server correlation identifier.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "rateLimited": {
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Please try again later."
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "PaymentSignatureHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "PAYMENT-SIGNATURE",
        "description": "Signed x402 payment payload. No account or API key is required."
      }
    },
    "schemas": {
      "LocationResolutionRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "locationDetails"
        ],
        "properties": {
          "agentCustomerId": {
            "type": "string",
            "pattern": "^agt_[A-Za-z0-9_-]{8,80}$"
          },
          "clientRequestId": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.:-]{1,100}$"
          },
          "locationDetails": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000,
            "description": "A landmark, partial name, full address, neighborhood hint, coordinates, nearby reference, venue description, intersection, airport terminal, business name, or ambiguous human phrase."
          },
          "hints": {
            "$ref": "#/components/schemas/LocationHints"
          }
        }
      },
      "LocationHints": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "region": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "countryCode": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "Two-letter country code. The service normalizes it to uppercase."
          },
          "near": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "languageCode": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})?$"
          },
          "timezone": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "coordinates": {
            "$ref": "#/components/schemas/Coordinates"
          }
        }
      },
      "Coordinates": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "latitude",
          "longitude"
        ],
        "properties": {
          "latitude": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "longitude": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          }
        }
      },
      "LocationResolutionResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "resolutionId",
          "status",
          "ambiguityStatus",
          "confidence",
          "originalRequest"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "2026-08-05"
          },
          "resolutionId": {
            "type": "string",
            "pattern": "^locres_[a-f0-9]{32}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "resolved",
              "ambiguous",
              "unresolved",
              "unsupported"
            ]
          },
          "ambiguityStatus": {
            "type": "string",
            "enum": [
              "single_match",
              "multiple_matches",
              "no_confident_match",
              "not_location_related"
            ]
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "originalRequest": {
            "$ref": "#/components/schemas/LocationResolutionRequest"
          },
          "result": {
            "$ref": "#/components/schemas/ResolvedLocationDetails"
          },
          "attribution": {
            "$ref": "#/components/schemas/LocationAttribution"
          },
          "ambiguityCandidates": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "$ref": "#/components/schemas/LocationCandidate"
            }
          }
        }
      },
      "ResolvedLocationDetails": {
        "type": "object",
        "additionalProperties": false,
        "description": "All fields are optional. Omitted fields are unknown.",
        "properties": {
          "locationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "exactName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "formattedAddress": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "stateOrProvince": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "postalCode": {
            "type": "string",
            "minLength": 1,
            "maxLength": 40
          },
          "countryCode": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "latitude": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "longitude": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "categories": {
            "$ref": "#/components/schemas/StringArray"
          },
          "traits": {
            "$ref": "#/components/schemas/StringArray"
          },
          "summary": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          },
          "operatingStatus": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "openingHours": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000
          },
          "phone": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "website": {
            "type": "string",
            "format": "uri",
            "maxLength": 1000
          },
          "rating": {
            "type": "number",
            "minimum": 0,
            "maximum": 5
          },
          "ratingCount": {
            "type": "integer",
            "minimum": 0
          },
          "priceTier": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "accessibility": {
            "$ref": "#/components/schemas/StringArray"
          },
          "amenities": {
            "$ref": "#/components/schemas/StringArray"
          }
        }
      },
      "LocationCandidate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "locationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "exactName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "formattedAddress": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "stateOrProvince": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "countryCode": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "latitude": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "longitude": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "LocationAttribution": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "required",
          "displayName",
          "instructions",
          "sources"
        ],
        "properties": {
          "required": {
            "type": "boolean",
            "const": true
          },
          "displayName": {
            "type": "string",
            "description": "Display this value exactly as provided by the service."
          },
          "instructions": {
            "type": "string",
            "const": "Present these sources immediately after the supported location result."
          },
          "sources": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/LocationAttributionSource"
            }
          }
        }
      },
      "LocationAttributionSource": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "title",
          "uri"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "uri": {
            "type": "string",
            "format": "uri",
            "maxLength": 1000
          },
          "placeId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          }
        }
      },
      "StringArray": {
        "type": "array",
        "maxItems": 50,
        "items": {
          "type": "string",
          "minLength": 1,
          "maxLength": 120
        }
      },
      "ErrorResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
