# Projects

A project is one tracked brand: its domain, locale, prompts and competitors. Almost every other endpoint takes a `project_id`, so start here.

### GET `/dimensions/projects`

Lists the authenticated user’s projects (this is also an auth check).

### GET `/dimensions/projects/:id`

Get detailed information about a project: matching names, industry, business model, prompt counts per brand focus, and `data_coverage` (the models, countries and languages that actually have data), so one call replaces separate models/locales lookups.

### GET `/dimensions/models`

Lists models present in daily metrics for the project.

### GET `/dimensions/locales`

Lists countries and languages present in daily metrics for the project.

### POST `/projects`

Create a complete project in one call (fast mode): project, prompts (queued for execution + categorization), competitors, weekly email subscription. Idempotent when `external_identifier` is provided. The project always belongs to the account owner.

- Body (JSON): `website_url` (required public HTTP(S) URL with a DNS hostname or public IP address; credentials, private and special IP addresses, localhost and internal hostnames are rejected), `name` (required), `main_country` (required), `main_language` (required), `brand_name`, `description`, `industry` (array), `business_model`, `target_audience`, `brand_voice`, `goals`, `primary_products` (array), `matching_names` (array), `prompts` (array, max 100), `competitors` (array of {domain, brand_name, matching_names}), `owned_media` (object, Growth+), `use_subdomain`, `weekly_email_subscribed`, `external_identifier` (embed-enabled accounts only; idempotency key, \[a-z0-9_-\]{1,64}), `execute_prompts_immediately` (default true).

### PATCH `/projects/:id`

Update the project profile (the Brand Book plus brand matching), the same fields as Project Settings. All seven Brand Book fields (`industry`, `business_model`, `description`, `primary_products`, `target_audience`, `brand_voice`, `goals`) feed every GEO Writer task and prompt suggestions. `industry`, `description`, and `target_audience` also help Recommendations calibrate their advice. Changing `matching_names` re-runs mention/citation matching over the project history in the background (`rematching: true`, edits blocked meanwhile); a `brand_name` change applies to future runs only. Unknown fields are rejected.

- Body (JSON), send only the fields to change: `brand_name`, `description`, `industry` (single key), `business_model`, `target_audience`, `brand_voice`, `goals`, `primary_products` (full replacement array), `matching_names` (FULL replacement array; send every variant to keep).

### Project Drafts wizard

Multi-step project wizard with AI suggestions: POST `/project_drafts` starts a draft (returns suggested name/description/industry for the URL), PATCH submits each step (details, prompts, competitors, owned_media) with strict forward gating and returns suggestions for the next step, POST `/project_drafts/:id/finalize` creates the real project. Drafts expire after 24h.

- The initial `website_url` must be a public HTTP(S) URL with a DNS hostname or public IP address. Credentials, private and special IP addresses, localhost and internal hostnames are rejected. Steps: `details` (name required), `prompts` (max 100, quota-validated), `competitors` (plan-capped), `owned_media` (optional, Growth+). Suggestions per step with `suggest=false` opt-out; cold URLs can take up to ~2 minutes, set client timeout to 180s. Finalize is idempotent and re-validates every gate.
