API ReferencePOST /v1/businesses/search

POST /v1/businesses/search

Find the right Google Places match for a business name before creating a site. Strongly recommended for common business names (e.g., “Acme Plumbing”, “Pizza Place”) — without this step, POST /v1/sites silently picks whichever Google ranks first, which can be the wrong business.

When to call this

Two paths into POST /v1/sites:

PathWhen to use
Direct — pass businessName onlyBusiness name is unique enough that the first Places match is reliably correct.
Disambiguated — call search-businesses first, pass placeId to create-siteAnytime you’re not sure. Always for LLM-agent flows where the model receives only a name from the user.

The disambiguated path is two API calls but eliminates an entire class of “Warpweb built the wrong business’s site” failures.

Request

POST /v1/businesses/search
Authorization: Bearer wwk_...
Content-Type: application/json
 
{
  "query": "Acme Plumbing",
  "location": "Austin, TX"
}

Body

FieldTypeRequiredDescription
querystringyesBusiness name (or any text Google Places will search for).
locationstringnoFree-form location hint that narrows the search (“Austin TX”, “78704”, “near downtown Dallas”). Omit for global searches; include for any business whose name might collide across cities.

Response

{
  "results": [
    {
      "placeId": "ChIJ_example_brookside_plumbing_austin_tx",
      "name": "Acme Plumbing & Drain",
      "address": "123 Main St, Austin, TX 78701, USA",
      "phone": "+1 512-555-0123",
      "rating": 4.7,
      "userRatingCount": 184,
      "website": "https://acmeplumbing.example.com",
      "googleMapsUri": "https://maps.google.com/?cid=12345",
      "businessType": "plumber"
    }
  ]
}

Returns up to 5 candidates, ordered by Google Places ranking. Each result includes enough context (address, rating, phone) to disambiguate visually or programmatically.

Result fields

FieldTypeDescription
placeIdstringGoogle Places ID. Pass this to POST /v1/sites as the placeId field for exact match.
namestringBusiness name as listed on Google Maps.
addressstring | nullFull formatted address.
phonestring | nullPhone number in international format if available.
ratingnumber | nullAverage Google review rating (0–5).
userRatingCountnumber | nullNumber of Google reviews. Useful as a signal — established businesses usually have more reviews.
websitestring | nullExisting website if listed.
googleMapsUristring | nullDirect link to the business on Google Maps. Useful for surfacing in confirmation UIs (“is this the right one?”).
businessTypestring | nullGoogle Places category (plumber, dentist, restaurant, etc.) — informs our vertical-aware template selection downstream.

Fields beyond the above are returned but treated as internal and subject to change — don’t depend on them.

Errors

StatusBodyCause
400{ "error": "Request body must be valid JSON" }Body wasn’t parseable JSON.
400{ "error": "\"query\" is required in the request body" }Missing or empty query field.
401{ "error": "Invalid or revoked API key" }See Authentication.
429{ "error": "Rate limit exceeded. Max 30 requests per minute." }Standard gateway rate limit.
500{ "error": "..." }Upstream Google Places error. Retry with backoff.

Cost

Free. This endpoint isn’t metered against your credit balance — only create-site and create-revision consume credits.

Two-step flow example

// 1. Disambiguate
const search = await fetch("https://api.warpweb.ai/v1/businesses/search", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.WARPWEB_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ query: "Acme Plumbing", location: "Austin, TX" }),
}).then(r => r.json())
 
// User (or LLM agent) picks the right one from `search.results`
const chosen = search.results[0]
 
// 2. Build the site with the exact placeId
const build = await fetch("https://api.warpweb.ai/v1/sites", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.WARPWEB_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    businessName: chosen.name,
    contactEmail: "owner@acmeplumbing.example.com",
    placeId: chosen.placeId,
  }),
}).then(r => r.json())
 
console.log("Building site:", build.siteId)

Notes for LLM-agent flows

If you’re routing user requests through an LLM agent into Warpweb (via an MCP server or your own integration), always make this call first when the user gives you just a business name. Present the top 2–3 candidates back to the user with a short summary (city, rating count) and let them confirm. This is the difference between a magical “I made a website for you in one prompt” experience and a frustrating “you built a site for the wrong Acme.”