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:
| Phase | Behavior |
|---|---|
researching (or any earlier phase) | 409 with { error, status, generation_phase }. Poll GET /v1/sites/:id until phase advances. |
research_review, generating, reviewing, deploying, complete | Full 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
| Field | Type | Description |
|---|---|---|
business_description | string | One-sentence summary of the business. Pulled from the operator’s input, the existing-site extractor, or a generated default — in that priority order. |
services | array | Services the site will feature. { name, description?, price? }. Edit by sending services to approve-research or research-draft. |
faqs | array | Question/answer pairs the FAQ section will use. { question, answer }. Empty answer means the generator will write one. |
testimonials | array | { quote, author?, source? }. |
hours | object | Weekday → human-readable hour string (e.g. "Monday": "9:00 AM - 5:00 PM" or "Closed"). |
photos | array | Photo 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_colors | string[] | Hex colors extracted from the logo or existing site, ordered primary → secondary → accent. |
competitor_positioning | string[] | Unique selling points pulled from competitor analysis. Used to seed differentiation copy. |
content_plan | object | Per-page slot for the generated content plan. home.plan is the populated slot today; services, about, contact are reserved. |
existing_site_url | string | null | The URL the operator supplied at create time, if any. |
design_style | string | null | Design style picked at create time (auto-selected or operator override). |
business_category | string | null | Coarse category — service, restaurant, retail, professional, or default. Drives category-aware section labels. |
contact_email | string | null | The 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_status | string | Three-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. |
status | string | The site’s overall status (generating, complete, failed). |
generation_phase | string | The 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
| Status | Body | Cause |
|---|---|---|
| 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. |
Related
POST /v1/sites/:id/approve-research— advance fromresearch_reviewinto generation, optionally with edits.PATCH /v1/sites/:id/research-draft— checkpoint edits without advancing.site.research_readywebhook — fires when this payload becomes available.