API ReferenceGET /v1/sites/:id/research

GET /v1/sites/:id/research

Fetch the research payload Warpweb assembled for a site — Google Places business data, competitor analysis, the content plan (services, FAQs, testimonials, key selling points), the photo library, and brand colors. This is the input the generator will build from. Use it in manual-review mode to inspect what’s about to ship before approving.

Cost: Free.

When it’s available

Only meaningful once research is done. The response shape depends on generation_phase:

PhaseBehavior
researching (or any earlier phase)409 with { error, status, generation_phase }. Poll GET /v1/sites/:id until phase advances.
research_review, generating, reviewing, deploying, completeFull payload returned.

In auto mode (default for public-API sites) the research_review window is brief — the build auto-advances the moment research completes. In manual mode ("review": "manual" on create) the site stays in research_review indefinitely until you POST to /v1/sites/:id/approve-research.

Request

curl https://api.warpweb.ai/v1/sites/8f3c2a1b-5d47-4c9e-b820-1f8a3e7d9c4f/research \
  -H "Authorization: Bearer wwk_<your-key>"

Response

{
  "business_description": "Residential plumbing services in Austin, TX",
  "services": [
    { "name": "Drain cleaning", "description": "Hydro-jetting and cabling for clogged lines." },
    { "name": "Water-heater install", "description": "Tank and tankless replacements." },
    { "name": "Slab leak detection" }
  ],
  "faqs": [
    {
      "question": "Do you offer 24/7 emergency service?",
      "answer": "Yes — we dispatch within 60 minutes for after-hours calls in central Austin."
    }
  ],
  "testimonials": [
    {
      "quote": "They fixed our slab leak the same day. Fair price, no upsell.",
      "author": "Maria G."
    }
  ],
  "hours": {
    "Monday": "8:00 AM - 6:00 PM",
    "Tuesday": "8:00 AM - 6:00 PM",
    "Wednesday": "8:00 AM - 6:00 PM",
    "Thursday": "8:00 AM - 6:00 PM",
    "Friday": "8:00 AM - 6:00 PM",
    "Saturday": "9:00 AM - 2:00 PM",
    "Sunday": "Closed"
  },
  "photos": [
    {
      "url": "research/photo-1.jpg",
      "localPath": "research/photo-1.jpg",
      "source": "google",
      "alt": "Technician working on a water heater"
    }
  ],
  "brand_colors": ["#0F4C81", "#F4A261", "#264653"],
  "competitor_positioning": [
    "Upfront flat-rate pricing",
    "Licensed master plumber on every call",
    "Lifetime warranty on fixtures"
  ],
  "content_plan": {
    "home": { "plan": { "servicesToHighlight": ["Drain cleaning", "Water-heater install"], "faqTopics": [], "competitiveAdvantages": [] } },
    "services": {},
    "about": {},
    "contact": {}
  },
  "existing_site_url": "https://brooksideplumbing.com",
  "design_style": "Clean Modern",
  "business_category": "service",
  "contact_email": "owner@brooksideplumbing.com",
  "email_status": "confirmed",
  "status": "generating",
  "generation_phase": "research_review"
}

Top-level fields

FieldTypeDescription
business_descriptionstringOne-sentence summary of the business. Pulled from the operator’s input, the existing-site extractor, or a generated default — in that priority order.
servicesarrayServices the site will feature. { name, description?, price? }. Edit by sending services to approve-research or research-draft.
faqsarrayQuestion/answer pairs the FAQ section will use. { question, answer }. Empty answer means the generator will write one.
testimonialsarray{ quote, author?, source? }.
hoursobjectWeekday → human-readable hour string (e.g. "Monday": "9:00 AM - 5:00 PM" or "Closed").
photosarrayPhoto library available to the generator. Each entry has url, localPath, source (google / unsplash / facebook / upload / existing_site), optional alt and exclude. Pass localPath values to excludeImages on approve-research to drop specific photos before generation.
brand_colorsstring[]Hex colors extracted from the logo or existing site, ordered primary → secondary → accent.
competitor_positioningstring[]Unique selling points pulled from competitor analysis. Used to seed differentiation copy.
content_planobjectPer-page slot for the generated content plan. home.plan is the populated slot today; services, about, contact are reserved.
existing_site_urlstring | nullThe URL the operator supplied at create time, if any.
design_stylestring | nullDesign style picked at create time (auto-selected or operator override).
business_categorystring | nullCoarse category — service, restaurant, retail, professional, or default. Drives category-aware section labels.
contact_emailstring | nullThe current best-guess email from the cascade — what your review-sheet should pre-fill. Comes from the caller, the website scrape, or operator entry on /approve-research, in that priority order. See Email resolution.
email_statusstringThree-state enum: confirmed (real business email, no nudge needed), placeholder (we’re using the operator’s own email — soft nudge to swap for the customer’s), or missing (no email anywhere — prominent prompt). Re-derived at read time so it tracks live changes from POST /v1/sites/:id/contact.
statusstringThe site’s overall status (generating, complete, failed).
generation_phasestringThe site’s current phase. Match this against GET /v1/sites/:id.

The response also includes a research summary object, plus extracted_content / extraction_confidence when the existing-site extractor ran. Treat fields not documented here as internal and subject to change.

Errors

StatusBodyCause
404{ "error": "Site not found" }No site with that ID belongs to your account.
404{ "error": "Research not yet complete" }The site exists but research hasn’t populated research_data yet.
409{ "error": "Research not ready for review", "status": "generating", "generation_phase": "researching" }The site is still mid-research. Poll GET /v1/sites/:id until the phase advances.