{
  "openapi": "3.1.0",
  "info": {
    "title": "Park Graph parking tools",
    "version": "2.2.0",
    "description": "Find Park Graph parking near a point, read one lot, and hold a space or get the lot's pay page. These are the REST endpoints behind the Park Graph MCP server's search_lots, get_lot and reserve tools; each operationId is the tool's name. No API key or sign-in: per IP, 60 lot searches, 100 lot reads and 5 holds a minute. Every payment completes on parkgraph.com with the driver present; no tool charges money on its own. The quote, session and signed-in tools are on the MCP server only: https://parkgraph.com/api/mcp.",
    "termsOfService": "https://parkgraph.com/legal/developers",
    "contact": {
      "name": "Park Graph",
      "url": "https://parkgraph.com/developers/mcp",
      "email": "support@parkgraph.com"
    }
  },
  "servers": [
    {
      "url": "https://parkgraph.com/api/v1",
      "description": "Production"
    }
  ],
  "paths": {
    "/lots/search": {
      "get": {
        "operationId": "search_lots",
        "summary": "Search for available parking lots by coordinates",
        "description": "Returns parking lots with real-time availability, pricing, and features using geospatial search. Works without an API key (60 requests a minute per IP); a key, if sent, must be valid.",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "Latitude of the search center",
            "example": 39.6403
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "Longitude of the search center",
            "example": -106.3742
          },
          {
            "name": "radius_km",
            "in": "query",
            "schema": {
              "type": "number",
              "default": 5
            },
            "description": "Search radius in kilometers"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 10
            },
            "description": "Maximum results to return"
          }
        ],
        "responses": {
          "200": {
            "description": "List of matching parking lots",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "lots",
                    "summary",
                    "meta"
                  ],
                  "properties": {
                    "lots": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "name",
                          "slug",
                          "address",
                          "city",
                          "state",
                          "latitude",
                          "longitude",
                          "lat",
                          "lng",
                          "total_spaces",
                          "lot_type",
                          "availability",
                          "pricing"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string",
                            "example": "Eagle County Airport Parking"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "address": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "state": {
                            "type": "string"
                          },
                          "latitude": {
                            "type": "number",
                            "description": "Lot latitude (WGS 84). Lots without a valid point are left out of results."
                          },
                          "longitude": {
                            "type": "number",
                            "description": "Lot longitude (WGS 84)."
                          },
                          "lat": {
                            "type": "number",
                            "description": "Same as latitude, for map libraries."
                          },
                          "lng": {
                            "type": "number",
                            "description": "Same as longitude, for map libraries."
                          },
                          "total_spaces": {
                            "type": "integer"
                          },
                          "lot_type": {
                            "type": "string",
                            "enum": [
                              "surface",
                              "garage",
                              "underground",
                              "rooftop",
                              "valet",
                              "street"
                            ]
                          },
                          "distance_km": {
                            "type": "number"
                          },
                          "verified": {
                            "type": "boolean",
                            "description": "Whether the lot owner has completed property verification"
                          },
                          "availability": {
                            "type": "object",
                            "required": [
                              "total_spaces",
                              "active_sessions",
                              "available_spaces",
                              "occupancy_pct",
                              "is_full"
                            ],
                            "properties": {
                              "total_spaces": {
                                "type": "integer"
                              },
                              "active_sessions": {
                                "type": "integer"
                              },
                              "available_spaces": {
                                "type": "integer"
                              },
                              "occupancy_pct": {
                                "type": "number"
                              },
                              "is_full": {
                                "type": "boolean"
                              }
                            }
                          },
                          "pricing": {
                            "type": "object",
                            "description": "Can be null.",
                            "required": [
                              "base_rate",
                              "rate_unit",
                              "max_daily_rate",
                              "currency"
                            ],
                            "properties": {
                              "base_rate": {
                                "type": "number"
                              },
                              "rate_unit": {
                                "type": "string",
                                "enum": [
                                  "hour",
                                  "day",
                                  "flat"
                                ]
                              },
                              "max_daily_rate": {
                                "type": "number",
                                "description": "Can be null."
                              },
                              "currency": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "summary": {
                      "type": "string",
                      "description": "One-line answer an assistant can quote. The MCP search_lots tool returns the same field.",
                      "example": "3 lots within 5 km. Top: Main Street Garage (0.4 km, $8/hr, 12 left); Center Lot (0.9 km, $6/hr, full); East Lot (2.1 km, $5/hr, 30 left)."
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "lat",
                        "lng",
                        "radius_km",
                        "count"
                      ],
                      "properties": {
                        "lat": {
                          "type": "number"
                        },
                        "lng": {
                          "type": "number"
                        },
                        "radius_km": {
                          "type": "number"
                        },
                        "count": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key sent is missing its Bearer prefix, invalid, revoked or expired. Send no Authorization header to search without a key."
          },
          "429": {
            "description": "RATE_LIMITED. Over 60 keyless requests a minute from this IP, or over the key's plan limit. Wait for Retry-After."
          }
        }
      }
    },
    "/lots/{lotId}": {
      "get": {
        "operationId": "get_lot",
        "summary": "Get one lot's public details",
        "description": "Address, coordinates, spaces, features, hours, pricing, spaces taken right now, the price of one hour now, and booking.mode: reserve (POST /reserve holds a space) or pay_at_qr_page (booking.pay_url is the lot's pay page). No API key needed. Every payment completes on parkgraph.com with the driver present; no tool charges money on its own.",
        "parameters": [
          {
            "name": "lotId",
            "in": "path",
            "required": true,
            "description": "Lot id from search_lots",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The lot",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "lot"
                  ],
                  "properties": {
                    "lot": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "slug": {
                          "type": "string"
                        },
                        "address": {
                          "type": "string"
                        },
                        "city": {
                          "type": "string"
                        },
                        "state": {
                          "type": "string"
                        },
                        "zip": {
                          "type": "string"
                        },
                        "latitude": {
                          "type": "number",
                          "description": "Can be null."
                        },
                        "longitude": {
                          "type": "number",
                          "description": "Can be null."
                        },
                        "total_spaces": {
                          "type": "integer"
                        },
                        "ev_spaces": {
                          "type": "integer"
                        },
                        "handicap_spaces": {
                          "type": "integer"
                        },
                        "oversized_spaces": {
                          "type": "integer"
                        },
                        "lot_type": {
                          "type": "string",
                          "enum": [
                            "surface",
                            "garage",
                            "underground",
                            "rooftop",
                            "valet",
                            "street"
                          ]
                        },
                        "features": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "operating_hours": {
                          "type": "object",
                          "description": "Opening hours by day. Can be null."
                        },
                        "pricing": {
                          "type": "object",
                          "description": "The lot's default rate. Can be null.",
                          "properties": {
                            "base_rate": {
                              "type": "number"
                            },
                            "rate_unit": {
                              "type": "string",
                              "enum": [
                                "hour",
                                "day",
                                "flat"
                              ]
                            },
                            "max_daily_rate": {
                              "type": "number",
                              "description": "Can be null."
                            },
                            "surge_enabled": {
                              "type": "boolean"
                            }
                          }
                        },
                        "current_quote": {
                          "type": "object",
                          "description": "The price the driver is charged, from the same engine as the driver page, reservations and agent tools. Amounts are integer cents (USD).",
                          "required": [
                            "duration_hours",
                            "currency",
                            "rate_unit",
                            "base_rate_cents",
                            "multiplier",
                            "effective_rate_cents",
                            "max_daily_cents",
                            "total_cents",
                            "capped_at_daily_max",
                            "surge"
                          ],
                          "properties": {
                            "duration_hours": {
                              "type": "number"
                            },
                            "currency": {
                              "type": "string",
                              "example": "usd"
                            },
                            "rate_unit": {
                              "type": "string",
                              "enum": [
                                "hour",
                                "day",
                                "flat"
                              ],
                              "description": "flat while a flat event price applies"
                            },
                            "base_rate_cents": {
                              "type": "integer"
                            },
                            "multiplier": {
                              "type": "number",
                              "description": "Multiplier applied to the base rate (1 when no surge applies)"
                            },
                            "effective_rate_cents": {
                              "type": "integer"
                            },
                            "max_daily_cents": {
                              "type": "integer",
                              "description": "Can be null."
                            },
                            "total_cents": {
                              "type": "integer"
                            },
                            "capped_at_daily_max": {
                              "type": "boolean"
                            },
                            "surge": {
                              "type": "object",
                              "description": "Present while an event, Surge today or a dynamic rule raises the price (Pro and Enterprise lots only). Can be null.",
                              "properties": {
                                "active": {
                                  "type": "boolean"
                                },
                                "label": {
                                  "type": "string",
                                  "description": "The owner's event name, or \"Surge active\"",
                                  "example": "Game day"
                                },
                                "kind": {
                                  "type": "string",
                                  "enum": [
                                    "event",
                                    "surge_today",
                                    "busy_lot",
                                    "peak",
                                    "weekend",
                                    "stacked"
                                  ]
                                },
                                "multiplier": {
                                  "type": "number"
                                },
                                "event_price_cents": {
                                  "type": "integer",
                                  "description": "The owner's flat event price, when that is what applies Can be null."
                                },
                                "bound": {
                                  "type": "string",
                                  "description": "Which of the lot's limits held the price, if any Can be null.",
                                  "enum": [
                                    "floor",
                                    "cap",
                                    "daily_max",
                                    null
                                  ]
                                },
                                "description": {
                                  "type": "string",
                                  "example": "Game day · $18.00 per event"
                                }
                              }
                            }
                          }
                        },
                        "booking": {
                          "type": "object",
                          "description": "How to book here: mode is reserve, pay_at_qr_page (with pay_url) or not_bookable.",
                          "properties": {
                            "mode": {
                              "type": "string",
                              "enum": [
                                "reserve",
                                "pay_at_qr_page",
                                "not_bookable"
                              ]
                            },
                            "pay_url": {
                              "type": "string",
                              "format": "uri"
                            }
                          }
                        },
                        "current_occupancy": {
                          "type": "object",
                          "description": "Can be null.",
                          "properties": {
                            "active": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            },
                            "percentage": {
                              "type": "number"
                            },
                            "as_of": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND. No listed lot has this id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED. Over 100 requests a minute from this IP. Wait for Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/reserve": {
      "post": {
        "operationId": "reserve",
        "summary": "Hold a space and get a one-tap pay link for the driver",
        "description": "Holds a space at one lot at a frozen price and returns booking_url, the lot's pre-filled pay page. The driver confirms there with one tap and pays amount_due_cents. No API key needed; a pk_test_ key books sandbox lots. A Starter lot answers 403 with error.pay_url instead of a hold.",
        "externalDocs": {
          "description": "How booking through an assistant works",
          "url": "https://parkgraph.com/developers/openai-actions"
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Required unless the body has idempotency_key (8-200 characters). Repeating a key returns the same hold.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lot_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "The lot to hold, from search results. Without it, intent picks the lot."
                  },
                  "duration_hours": {
                    "type": "integer",
                    "enum": [
                      1,
                      2,
                      4,
                      8
                    ],
                    "description": "Hours to book; the pay page opens on this length. Default 2."
                  },
                  "plate": {
                    "type": "string",
                    "description": "Vehicle license plate, pre-filled on the pay page"
                  },
                  "agent_platform": {
                    "type": "string",
                    "enum": [
                      "chatgpt",
                      "claude",
                      "gemini",
                      "grok",
                      "perplexity",
                      "copilot",
                      "custom"
                    ],
                    "description": "The assistant booking. Recorded on the booking and the session."
                  },
                  "intent": {
                    "type": "string",
                    "description": "Plain-language request, used to find the lot when lot_id is omitted"
                  },
                  "idempotency_key": {
                    "type": "string",
                    "description": "For clients that can't send the Idempotency-Key header"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A hold with its pay link, or lot suggestions when no single lot matched. booking_url is signed with the hold and the assistant. The hold counts against the lot's capacity until the driver pays or it ends at hold.expires_at.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "held",
                        "suggestions"
                      ]
                    },
                    "hold": {
                      "type": "object",
                      "required": [
                        "id",
                        "expires_at",
                        "lot_name",
                        "reused",
                        "lot_id",
                        "duration_hours"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "lot_name": {
                          "type": "string"
                        },
                        "reused": {
                          "type": "boolean",
                          "description": "True when the Idempotency-Key matched an earlier hold"
                        },
                        "lot_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "lot_slug": {
                          "type": "string",
                          "description": "Can be null."
                        },
                        "duration_hours": {
                          "type": "number"
                        }
                      }
                    },
                    "quote": {
                      "type": "object",
                      "description": "The price the driver is charged, from the same engine as the driver page, reservations and agent tools. Amounts are integer cents (USD).",
                      "required": [
                        "duration_hours",
                        "currency",
                        "rate_unit",
                        "base_rate_cents",
                        "multiplier",
                        "effective_rate_cents",
                        "max_daily_cents",
                        "total_cents",
                        "capped_at_daily_max",
                        "surge"
                      ],
                      "properties": {
                        "duration_hours": {
                          "type": "number"
                        },
                        "currency": {
                          "type": "string",
                          "example": "usd"
                        },
                        "rate_unit": {
                          "type": "string",
                          "enum": [
                            "hour",
                            "day",
                            "flat"
                          ],
                          "description": "flat while a flat event price applies"
                        },
                        "base_rate_cents": {
                          "type": "integer"
                        },
                        "multiplier": {
                          "type": "number",
                          "description": "Multiplier applied to the base rate (1 when no surge applies)"
                        },
                        "effective_rate_cents": {
                          "type": "integer"
                        },
                        "max_daily_cents": {
                          "type": "integer",
                          "description": "Can be null."
                        },
                        "total_cents": {
                          "type": "integer"
                        },
                        "capped_at_daily_max": {
                          "type": "boolean"
                        },
                        "surge": {
                          "type": "object",
                          "description": "Present while an event, Surge today or a dynamic rule raises the price (Pro and Enterprise lots only). Can be null.",
                          "properties": {
                            "active": {
                              "type": "boolean"
                            },
                            "label": {
                              "type": "string",
                              "description": "The owner's event name, or \"Surge active\"",
                              "example": "Game day"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "event",
                                "surge_today",
                                "busy_lot",
                                "peak",
                                "weekend",
                                "stacked"
                              ]
                            },
                            "multiplier": {
                              "type": "number"
                            },
                            "event_price_cents": {
                              "type": "integer",
                              "description": "The owner's flat event price, when that is what applies Can be null."
                            },
                            "bound": {
                              "type": "string",
                              "description": "Which of the lot's limits held the price, if any Can be null.",
                              "enum": [
                                "floor",
                                "cap",
                                "daily_max",
                                null
                              ]
                            },
                            "description": {
                              "type": "string",
                              "example": "Game day · $18.00 per event"
                            }
                          }
                        }
                      }
                    },
                    "agent_platform": {
                      "type": "string"
                    },
                    "agent_surcharge_cents": {
                      "type": "integer",
                      "description": "The lot's agent surcharge, frozen in the hold (0 when none). Itemized on the pay page and the receipt."
                    },
                    "amount_due_cents": {
                      "type": "integer",
                      "description": "What the driver pays at booking_url, quote.total_cents plus agent_surcharge_cents"
                    },
                    "booking_url": {
                      "type": "string",
                      "description": "The lot's pay page, pre-filled and signed. Give it to the driver. Can be null.",
                      "format": "uri"
                    },
                    "suggestions": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The lot takes payment at its QR page (error.pay_url), its owner turned this assistant off (AGENT_PLATFORM_OFF), or its owner turned off AI agent bookings for the lot (AGENT_BOOKING_OFF)"
          },
          "404": {
            "description": "Lot not found or not open for reservations"
          },
          "409": {
            "description": "lot_full. The lot is full right now; suggestions lists nearby lots."
          },
          "429": {
            "description": "RATE_LIMITED. Too many holds; wait for Retry-After."
          }
        }
      }
    }
  }
}
