{
  "openapi": "3.1.0",
  "info": {
    "title": "SerpApi Google Search API Reference",
    "version": "1.0.0",
    "description": "SerpApi-compatible Google Search routes exposed by Lempile. Fresh browser-backed searches are queue-first: the API creates an archive record, returns HTTP 202 with polling endpoints, and the runner processes the search when capacity is available.",
    "contact": {}
  },
  "servers": [
    {
      "url": "https://api.lempile.com",
      "description": "Primary Lempile production API host."
    }
  ],
  "tags": [
    {
      "name": "SerpApi Google Search",
      "description": "SerpApi-compatible Google organic Search API backed by Lempile, Donut Browser, managed proxies, and browser-harness.",
      "externalDocs": {
        "url": "https://serpapi.com/search-api",
        "description": "Compatibility target: SerpApi Google Search API."
      }
    }
  ],
  "paths": {
    "/search": {
      "get": {
        "operationId": "SerpApiGoogleController_search",
        "tags": [
          "SerpApi Google Search"
        ],
        "summary": "Search Google",
        "description": "Create a SerpApi-compatible Google Search through the Lempile browser-backed search pipeline. Fresh non-cached searches are queue-first and normally return HTTP 202 with a `search_metadata.id` plus archive endpoints. Poll `search_metadata.json_endpoint` until `search_metadata.status` becomes `Success` or `Error`. Cached successful searches may return HTTP 200 immediately. Authentication is accepted as either the `api_key` query parameter or the `X-API-KEY` header. This route requires the `search.write` scope.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "QueryApiKeyAuth": []
          }
        ],
        "x-readme": {
          "code-samples": [
            {
              "language": "shell",
              "name": "Create and poll",
              "code": "SEARCH=$(curl -sS \"https://api.lempile.com/search.json?engine=google&q=Coffee&location=Austin%2C+Texas%2C+United+States&hl=en&gl=us&api_key=secret_api_key\")\nJSON_ENDPOINT=$(node -e 'const payload = JSON.parse(process.argv[1]); console.log(payload.search_metadata.json_endpoint)' \"$SEARCH\")\n\nwhile true; do\n  RESULT=$(curl -sS \"$JSON_ENDPOINT?api_key=secret_api_key\")\n  STATUS=$(node -e 'const payload = JSON.parse(process.argv[1]); console.log(payload.search_metadata.status)' \"$RESULT\")\n  echo \"status=$STATUS\"\n  [ \"$STATUS\" != \"Processing\" ] && break\n  sleep 5\ndone\n\necho \"$RESULT\""
            },
            {
              "language": "node",
              "name": "Node",
              "code": "const BASE_URL = \"https://api.lempile.com\";\nconst apiKey = \"your-api-key\";\n\nconst url = new URL(`${BASE_URL}/search.json`);\nurl.searchParams.set(\"engine\", \"google\");\nurl.searchParams.set(\"q\", \"Coffee\");\nurl.searchParams.set(\"location\", \"Austin, Texas, United States\");\nurl.searchParams.set(\"hl\", \"en\");\nurl.searchParams.set(\"gl\", \"us\");\n\nconst created = await fetch(url, {\n  headers: { \"X-API-KEY\": apiKey },\n}).then((response) => response.json());\n\nlet result = created;\nwhile (result.search_metadata.status === \"Processing\") {\n  await new Promise((resolve) => setTimeout(resolve, 5000));\n  result = await fetch(result.search_metadata.json_endpoint, {\n    headers: { \"X-API-KEY\": apiKey },\n  }).then((response) => response.json());\n}\n\nconsole.log(result.search_metadata.status, result.organic_results?.length ?? 0);"
            }
          ]
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Engine"
          },
          {
            "$ref": "#/components/parameters/Query"
          },
          {
            "$ref": "#/components/parameters/Location"
          },
          {
            "$ref": "#/components/parameters/Uule"
          },
          {
            "$ref": "#/components/parameters/Lat"
          },
          {
            "$ref": "#/components/parameters/Lon"
          },
          {
            "$ref": "#/components/parameters/Radius"
          },
          {
            "$ref": "#/components/parameters/GoogleDomain"
          },
          {
            "$ref": "#/components/parameters/Hl"
          },
          {
            "$ref": "#/components/parameters/Gl"
          },
          {
            "$ref": "#/components/parameters/Cr"
          },
          {
            "$ref": "#/components/parameters/Lr"
          },
          {
            "$ref": "#/components/parameters/Tbs"
          },
          {
            "$ref": "#/components/parameters/Safe"
          },
          {
            "$ref": "#/components/parameters/Nfpr"
          },
          {
            "$ref": "#/components/parameters/Filter"
          },
          {
            "$ref": "#/components/parameters/Tbm"
          },
          {
            "$ref": "#/components/parameters/Start"
          },
          {
            "$ref": "#/components/parameters/Device"
          },
          {
            "$ref": "#/components/parameters/NoCache"
          },
          {
            "$ref": "#/components/parameters/Async"
          },
          {
            "$ref": "#/components/parameters/ZeroTrace"
          },
          {
            "$ref": "#/components/parameters/AdvancedGoogleParameterLudocid"
          },
          {
            "$ref": "#/components/parameters/AdvancedGoogleParameterLsig"
          },
          {
            "$ref": "#/components/parameters/AdvancedGoogleParameterKgmid"
          },
          {
            "$ref": "#/components/parameters/AdvancedGoogleParameterSi"
          },
          {
            "$ref": "#/components/parameters/AdvancedGoogleParameterIbp"
          },
          {
            "$ref": "#/components/parameters/AdvancedGoogleParameterUds"
          },
          {
            "$ref": "#/components/parameters/ApiKeyQuery"
          },
          {
            "$ref": "#/components/parameters/Output"
          }
        ],
        "responses": {
          "200": {
            "description": "A cached successful search was returned immediately, or `output=html` returned cached raw Google HTML.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpApiGoogleSearchResult"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string",
                  "description": "Raw Google Search HTML from a cached successful browser run."
                }
              }
            }
          },
          "202": {
            "description": "Fresh search accepted and queued. Poll `search_metadata.json_endpoint` until the public status changes from `Processing` to `Success` or `Error`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpApiProcessingSearch"
                },
                "examples": {
                  "queued": {
                    "$ref": "#/components/examples/QueuedSearch"
                  },
                  "running": {
                    "$ref": "#/components/examples/RunningSearch"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/WorkspaceQueueFull"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/search.json": {
      "get": {
        "operationId": "SerpApiGoogleController_searchJson",
        "tags": [
          "SerpApi Google Search"
        ],
        "summary": "Search Google as JSON",
        "description": "JSON-suffixed alias for `GET /search`. Fresh non-cached searches are queue-first and return HTTP 202 with polling endpoints. Poll `search_metadata.json_endpoint` until `search_metadata.status` becomes `Success` or `Error`.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "QueryApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Engine"
          },
          {
            "$ref": "#/components/parameters/Query"
          },
          {
            "$ref": "#/components/parameters/Location"
          },
          {
            "$ref": "#/components/parameters/GoogleDomain"
          },
          {
            "$ref": "#/components/parameters/Hl"
          },
          {
            "$ref": "#/components/parameters/Gl"
          },
          {
            "$ref": "#/components/parameters/Tbs"
          },
          {
            "$ref": "#/components/parameters/Start"
          },
          {
            "$ref": "#/components/parameters/Device"
          },
          {
            "$ref": "#/components/parameters/NoCache"
          },
          {
            "$ref": "#/components/parameters/ApiKeyQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "A cached successful search was returned immediately.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpApiGoogleSearchResult"
                }
              }
            }
          },
          "202": {
            "description": "Fresh search accepted and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpApiProcessingSearch"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/WorkspaceQueueFull"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/searches/{searchId}.json": {
      "get": {
        "operationId": "SerpApiGoogleController_retrieveJson",
        "tags": [
          "SerpApi Google Search"
        ],
        "summary": "Retrieve archived Google search JSON",
        "description": "Poll or retrieve the JSON archive for a Google search. Pending internal `Queued`, `Running`, and legacy `Processing` rows return HTTP 202 with public status `Processing`. Final rows return HTTP 200 with public status `Success` or `Error`. This route requires the `search.read` scope.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "QueryApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchId"
          },
          {
            "$ref": "#/components/parameters/ApiKeyQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Final archived search JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpApiGoogleSearchResult"
                },
                "examples": {
                  "success": {
                    "$ref": "#/components/examples/SuccessfulSearch"
                  },
                  "error": {
                    "$ref": "#/components/examples/FailedSearch"
                  }
                }
              }
            }
          },
          "202": {
            "description": "Search is queued or running. Continue polling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpApiProcessingSearch"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenRead"
          },
          "404": {
            "$ref": "#/components/responses/SearchNotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/searches/{searchId}.html": {
      "get": {
        "operationId": "SerpApiGoogleController_retrieveHtml",
        "tags": [
          "SerpApi Google Search"
        ],
        "summary": "Retrieve archived Google search HTML",
        "description": "Retrieve raw Google HTML for a successful browser-backed search. Pending rows return HTTP 202 with the same processing JSON used by archive polling. This route requires the `search.read` scope.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "QueryApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchId"
          },
          {
            "$ref": "#/components/parameters/ApiKeyQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Raw Google Search HTML captured from the browser run.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "Search is queued or running. Continue polling the JSON endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpApiProcessingSearch"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenRead"
          },
          "404": {
            "$ref": "#/components/responses/SearchNotFound"
          }
        }
      }
    },
    "/searches/{searchId}.json_with_pixel_position": {
      "get": {
        "operationId": "SerpApiGoogleController_retrieveJsonWithPixelPosition",
        "tags": [
          "SerpApi Google Search"
        ],
        "summary": "Retrieve archived Google search JSON with pixel positions",
        "description": "Retrieve final or pending search JSON plus `pixel_positions` when available. Pending rows return HTTP 202 and should be polled until the public status is no longer `Processing`. This route requires the `search.read` scope.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "QueryApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchId"
          },
          {
            "$ref": "#/components/parameters/ApiKeyQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Archived search JSON with pixel position data.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SerpApiGoogleSearchResult"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "pixel_positions": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Search is queued or running. Continue polling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpApiProcessingSearch"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenRead"
          },
          "404": {
            "$ref": "#/components/responses/SearchNotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY"
      },
      "QueryApiKeyAuth": {
        "type": "apiKey",
        "in": "query",
        "name": "api_key"
      }
    },
    "parameters": {
      "SearchId": {
        "name": "searchId",
        "in": "path",
        "required": true,
        "description": "Search archive id returned in `search_metadata.id`.",
        "schema": {
          "type": "string",
          "minLength": 8
        }
      },
      "Engine": {
        "name": "engine",
        "in": "query",
        "required": false,
        "description": "Search engine to use. Defaults to `google`; other engines return a SerpApi-style error.",
        "schema": {
          "type": "string",
          "default": "google",
          "enum": [
            "google"
          ]
        }
      },
      "Query": {
        "name": "q",
        "in": "query",
        "required": true,
        "description": "Google search query. Supports normal Google operators such as `site:`, `inurl:`, and quoted phrases. For LinkedIn discovery, use queries such as `site:linkedin.com/posts/ \"business inspiration\"`.",
        "schema": {
          "type": "string",
          "minLength": 1
        }
      },
      "Location": {
        "name": "location",
        "in": "query",
        "required": false,
        "description": "Human-readable origin location. Cannot be combined with `uule`, `lat`, or `lon`.",
        "schema": {
          "type": "string"
        }
      },
      "Uule": {
        "name": "uule",
        "in": "query",
        "required": false,
        "description": "Google encoded location token. Cannot be combined with `location`, `lat`, `lon`, or `radius`.",
        "schema": {
          "type": "string"
        }
      },
      "Lat": {
        "name": "lat",
        "in": "query",
        "required": false,
        "description": "GPS latitude. Must be paired with `lon` and cannot be combined with `location` or `uule`.",
        "schema": {
          "type": "number"
        }
      },
      "Lon": {
        "name": "lon",
        "in": "query",
        "required": false,
        "description": "GPS longitude. Must be paired with `lat` and cannot be combined with `location` or `uule`.",
        "schema": {
          "type": "number"
        }
      },
      "Radius": {
        "name": "radius",
        "in": "query",
        "required": false,
        "description": "Distance in meters used to bias local results. Desktop accepts 1..199; mobile and tablet accept 1..1000.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "GoogleDomain": {
        "name": "google_domain",
        "in": "query",
        "required": false,
        "description": "Google domain to use. Defaults to `google.com`.",
        "schema": {
          "type": "string",
          "default": "google.com"
        }
      },
      "Hl": {
        "name": "hl",
        "in": "query",
        "required": false,
        "description": "Google interface language, such as `en` or `fr`.",
        "schema": {
          "type": "string"
        }
      },
      "Gl": {
        "name": "gl",
        "in": "query",
        "required": false,
        "description": "Country code used for Google search localization, such as `us`, `uk`, or `fr`.",
        "schema": {
          "type": "string"
        }
      },
      "Cr": {
        "name": "cr",
        "in": "query",
        "required": false,
        "description": "Country restriction, for example `countryFR|countryDE`.",
        "schema": {
          "type": "string"
        }
      },
      "Lr": {
        "name": "lr",
        "in": "query",
        "required": false,
        "description": "Language restriction, for example `lang_fr|lang_de`.",
        "schema": {
          "type": "string"
        }
      },
      "Tbs": {
        "name": "tbs",
        "in": "query",
        "required": false,
        "description": "Advanced Google filter string, such as `qdr:m` for the last month.",
        "schema": {
          "type": "string"
        }
      },
      "Safe": {
        "name": "safe",
        "in": "query",
        "required": false,
        "description": "Adult content filter. Common values are `active` and `off`.",
        "schema": {
          "type": "string",
          "enum": [
            "active",
            "off"
          ]
        }
      },
      "Nfpr": {
        "name": "nfpr",
        "in": "query",
        "required": false,
        "description": "Set to `1` to exclude auto-corrected query results when possible.",
        "schema": {
          "type": "integer",
          "enum": [
            0,
            1
          ]
        }
      },
      "Filter": {
        "name": "filter",
        "in": "query",
        "required": false,
        "description": "Set to `0` to disable similar-results and omitted-results filtering; defaults to Google behavior.",
        "schema": {
          "type": "integer",
          "enum": [
            0,
            1
          ]
        }
      },
      "Tbm": {
        "name": "tbm",
        "in": "query",
        "required": false,
        "description": "Google vertical such as `isch`, `lcl`, `vid`, `nws`, `shop`, or `pts`. Organic web search with `tbm` omitted is the current parity milestone; vertical module parity is best-effort.",
        "schema": {
          "type": "string"
        }
      },
      "Start": {
        "name": "start",
        "in": "query",
        "required": false,
        "description": "Result offset for pagination. `0` is page 1, `10` is page 2, and so on.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        }
      },
      "Device": {
        "name": "device",
        "in": "query",
        "required": false,
        "description": "Browser profile type used for the run.",
        "schema": {
          "type": "string",
          "default": "desktop",
          "enum": [
            "desktop",
            "mobile",
            "tablet"
          ]
        }
      },
      "NoCache": {
        "name": "no_cache",
        "in": "query",
        "required": false,
        "description": "Set to `true` to bypass the 1-hour normalized-parameter cache and force a fresh queued browser-backed Google run. Cached successful searches may return immediately.",
        "schema": {
          "type": "boolean",
          "default": false
        }
      },
      "Async": {
        "name": "async",
        "in": "query",
        "required": false,
        "description": "Accepted for SerpApi compatibility. Lempile is queue-first by default, so fresh non-cached searches return HTTP 202 whether or not `async=true` is provided.",
        "schema": {
          "type": "boolean",
          "default": false
        }
      },
      "ZeroTrace": {
        "name": "zero_trace",
        "in": "query",
        "required": false,
        "description": "Accepted for SerpApi compatibility, but Lempile still archives requests for dashboard inspection and search retrieval.",
        "schema": {
          "type": "boolean",
          "default": false
        }
      },
      "AdvancedGoogleParameterLudocid": {
        "name": "ludocid",
        "in": "query",
        "required": false,
        "description": "Google place CID used for local or knowledge graph result variants.",
        "schema": {
          "type": "string"
        }
      },
      "AdvancedGoogleParameterLsig": {
        "name": "lsig",
        "in": "query",
        "required": false,
        "description": "Google local result signature when Google requires it for a specific view.",
        "schema": {
          "type": "string"
        }
      },
      "AdvancedGoogleParameterKgmid": {
        "name": "kgmid",
        "in": "query",
        "required": false,
        "description": "Google Knowledge Graph machine id.",
        "schema": {
          "type": "string"
        }
      },
      "AdvancedGoogleParameterSi": {
        "name": "si",
        "in": "query",
        "required": false,
        "description": "Google cached search parameter token.",
        "schema": {
          "type": "string"
        }
      },
      "AdvancedGoogleParameterIbp": {
        "name": "ibp",
        "in": "query",
        "required": false,
        "description": "Google layout or expansion parameter for selected modules.",
        "schema": {
          "type": "string"
        }
      },
      "AdvancedGoogleParameterUds": {
        "name": "uds",
        "in": "query",
        "required": false,
        "description": "Google filter token captured from a previous result page.",
        "schema": {
          "type": "string"
        }
      },
      "ApiKeyQuery": {
        "name": "api_key",
        "in": "query",
        "required": false,
        "description": "API key with `search.write` for search creation routes or `search.read` for archive routes. `X-API-KEY` may be used instead.",
        "schema": {
          "type": "string"
        }
      },
      "Output": {
        "name": "output",
        "in": "query",
        "required": false,
        "description": "Requested output format. `json` returns SerpApi-shaped JSON. `html` returns raw Google HTML only when a successful cached run is available; fresh browser runs still return HTTP 202 with polling metadata.",
        "schema": {
          "type": "string",
          "default": "json",
          "enum": [
            "json",
            "html"
          ]
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid search parameters.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SerpApiError"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SerpApiError"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The API key does not include the required `search.write` scope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SerpApiError"
            }
          }
        }
      },
      "ForbiddenRead": {
        "description": "The API key does not include the required `search.read` scope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SerpApiError"
            }
          }
        }
      },
      "WorkspaceQueueFull": {
        "description": "Workspace has reached the pending Google search queue cap.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SerpApiError"
            },
            "example": {
              "error": "Workspace Google search queue is full. Please wait for existing searches to finish before adding more.",
              "error_code": "workspace_search_queue_full"
            }
          }
        }
      },
      "SearchNotFound": {
        "description": "Search archive id was not found for the current workspace.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SerpApiError"
            },
            "example": {
              "error": "Search not found."
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Platform, configuration, or storage dependency is temporarily unavailable. New searches normally queue when the runner is at capacity or briefly unavailable.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SerpApiError"
            }
          }
        }
      }
    },
    "schemas": {
      "SerpApiError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "SerpApi-compatible error message."
          },
          "error_code": {
            "type": "string",
            "description": "Machine-readable Lempile error code when available."
          }
        },
        "required": [
          "error"
        ],
        "additionalProperties": true
      },
      "SerpApiSearchMetadata": {
        "type": "object",
        "description": "SerpApi-compatible lifecycle metadata. Internal `Queued` and `Running` states are exposed as public `Processing` plus detail fields.",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "Processing",
              "Success",
              "Error"
            ]
          },
          "status_detail": {
            "type": "string",
            "description": "Internal state such as `Queued`, `Running`, or a final status detail."
          },
          "runner_status_detail": {
            "type": "string",
            "description": "Runner detail such as `queued`, `runner_claimed`, `lease_renewed`, `completed`, `search_queue_timeout`, or `runner_lease_expired`."
          },
          "json_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "pixel_position_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "raw_html_file": {
            "type": "string",
            "format": "uri"
          },
          "created_at": {
            "type": "string"
          },
          "queued_at": {
            "type": "string"
          },
          "started_at": {
            "type": "string"
          },
          "lease_expires_at": {
            "type": "string"
          },
          "processed_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "google_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "total_time_taken": {
            "type": [
              "number",
              "null"
            ]
          },
          "captcha_autosolve": {
            "type": "object",
            "description": "Safe CAPTCHA autosolve summary when a Google block page required solving.",
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "status"
        ],
        "additionalProperties": true
      },
      "SerpApiSearchParameters": {
        "type": "object",
        "description": "Normalized search parameters used for the Google request.",
        "properties": {
          "engine": {
            "type": "string",
            "enum": [
              "google"
            ]
          },
          "q": {
            "type": "string"
          },
          "location_requested": {
            "type": [
              "string",
              "null"
            ]
          },
          "location_used": {
            "type": [
              "string",
              "null"
            ]
          },
          "google_domain": {
            "type": "string"
          },
          "hl": {
            "type": [
              "string",
              "null"
            ]
          },
          "gl": {
            "type": [
              "string",
              "null"
            ]
          },
          "tbs": {
            "type": [
              "string",
              "null"
            ]
          },
          "start": {
            "type": [
              "integer",
              "null"
            ]
          },
          "device": {
            "type": "string",
            "enum": [
              "desktop",
              "mobile",
              "tablet"
            ]
          }
        },
        "required": [
          "engine",
          "q",
          "google_domain",
          "device"
        ],
        "additionalProperties": true
      },
      "SerpApiSearchInformation": {
        "type": "object",
        "description": "High-level information extracted from the Google results page.",
        "properties": {
          "query_displayed": {
            "type": [
              "string",
              "null"
            ]
          },
          "total_results": {
            "type": [
              "integer",
              "null"
            ]
          },
          "time_taken_displayed": {
            "type": [
              "number",
              "null"
            ]
          },
          "organic_results_state": {
            "type": [
              "string",
              "null"
            ]
          },
          "page_number": {
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "additionalProperties": true
      },
      "SerpApiOrganicResult": {
        "type": "object",
        "description": "A SerpApi-shaped organic Google result.",
        "properties": {
          "position": {
            "type": "integer"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "link": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "displayed_link": {
            "type": [
              "string",
              "null"
            ]
          },
          "snippet": {
            "type": [
              "string",
              "null"
            ]
          },
          "snippet_highlighted_words": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "source": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "position"
        ],
        "additionalProperties": true
      },
      "SerpApiPagination": {
        "type": "object",
        "properties": {
          "current": {
            "type": "integer"
          },
          "previous": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "other_pages": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "format": "uri"
            }
          }
        },
        "additionalProperties": true
      },
      "SerpApiGoogleSearchResult": {
        "type": "object",
        "description": "SerpApi-compatible JSON for a Google Search result page. For final failures, `error` and `error_diagnostics` may be present.",
        "properties": {
          "error": {
            "type": "string"
          },
          "search_metadata": {
            "$ref": "#/components/schemas/SerpApiSearchMetadata"
          },
          "search_parameters": {
            "$ref": "#/components/schemas/SerpApiSearchParameters"
          },
          "search_information": {
            "$ref": "#/components/schemas/SerpApiSearchInformation"
          },
          "organic_results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SerpApiOrganicResult"
            }
          },
          "related_searches": {
            "type": "array",
            "description": "Real Google related-search suggestions only.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/SerpApiPagination"
          },
          "serpapi_pagination": {
            "$ref": "#/components/schemas/SerpApiPagination"
          },
          "error_diagnostics": {
            "type": "object",
            "description": "Safe failure diagnostics, including CAPTCHA provider metadata when available. Raw secrets, cookies, tokens, proxy credentials, and API keys are not included.",
            "additionalProperties": true
          }
        },
        "required": [
          "search_metadata",
          "search_parameters"
        ],
        "additionalProperties": true
      },
      "SerpApiProcessingSearch": {
        "type": "object",
        "description": "Processing payload returned while a search is queued or running.",
        "properties": {
          "search_metadata": {
            "$ref": "#/components/schemas/SerpApiSearchMetadata"
          },
          "search_parameters": {
            "$ref": "#/components/schemas/SerpApiSearchParameters"
          }
        },
        "required": [
          "search_metadata"
        ],
        "additionalProperties": true
      }
    },
    "examples": {
      "QueuedSearch": {
        "summary": "Queued fresh search",
        "value": {
          "search_metadata": {
            "id": "63c57c0222e0470397fda526",
            "status": "Processing",
            "status_detail": "Queued",
            "runner_status_detail": "queued",
            "created_at": "2026-06-01 07:35:00 UTC",
            "queued_at": "2026-06-01 07:35:00 UTC",
            "json_endpoint": "https://api.lempile.com/searches/63c57c0222e0470397fda526.json",
            "raw_html_file": "https://api.lempile.com/searches/63c57c0222e0470397fda526.html",
            "pixel_position_endpoint": "https://api.lempile.com/searches/63c57c0222e0470397fda526.json_with_pixel_position"
          },
          "search_parameters": {
            "engine": "google",
            "q": "Coffee",
            "google_domain": "google.com",
            "device": "desktop"
          }
        }
      },
      "RunningSearch": {
        "summary": "Running leased search",
        "value": {
          "search_metadata": {
            "id": "63c57c0222e0470397fda526",
            "status": "Processing",
            "status_detail": "Running",
            "runner_status_detail": "lease_renewed",
            "created_at": "2026-06-01 07:35:00 UTC",
            "queued_at": "2026-06-01 07:35:00 UTC",
            "started_at": "2026-06-01 07:35:03 UTC",
            "lease_expires_at": "2026-06-01 07:45:03 UTC",
            "json_endpoint": "https://api.lempile.com/searches/63c57c0222e0470397fda526.json",
            "raw_html_file": "https://api.lempile.com/searches/63c57c0222e0470397fda526.html",
            "pixel_position_endpoint": "https://api.lempile.com/searches/63c57c0222e0470397fda526.json_with_pixel_position"
          },
          "search_parameters": {
            "engine": "google",
            "q": "Coffee",
            "google_domain": "google.com",
            "device": "desktop"
          }
        }
      },
      "SuccessfulSearch": {
        "summary": "Successful search",
        "value": {
          "search_metadata": {
            "id": "63c57c0222e0470397fda526",
            "status": "Success",
            "status_detail": "completed",
            "created_at": "2026-06-01 07:35:00 UTC",
            "processed_at": "2026-06-01 07:35:22 UTC",
            "total_time_taken": 18.42,
            "json_endpoint": "https://api.lempile.com/searches/63c57c0222e0470397fda526.json",
            "raw_html_file": "https://api.lempile.com/searches/63c57c0222e0470397fda526.html",
            "pixel_position_endpoint": "https://api.lempile.com/searches/63c57c0222e0470397fda526.json_with_pixel_position"
          },
          "search_parameters": {
            "engine": "google",
            "q": "Coffee",
            "google_domain": "google.com",
            "device": "desktop"
          },
          "organic_results": []
        }
      },
      "FailedSearch": {
        "summary": "Failed search",
        "value": {
          "error": "Google returned a block or consent challenge page.",
          "search_metadata": {
            "id": "63c57c0222e0470397fda526",
            "status": "Error",
            "status_detail": "google_search_failed",
            "created_at": "2026-06-01 07:35:00 UTC",
            "processed_at": "2026-06-01 07:37:00 UTC",
            "json_endpoint": "https://api.lempile.com/searches/63c57c0222e0470397fda526.json",
            "raw_html_file": "https://api.lempile.com/searches/63c57c0222e0470397fda526.html",
            "pixel_position_endpoint": "https://api.lempile.com/searches/63c57c0222e0470397fda526.json_with_pixel_position"
          },
          "search_parameters": {
            "engine": "google",
            "q": "Coffee",
            "google_domain": "google.com",
            "device": "desktop"
          }
        }
      }
    }
  }
}
