# WebPlanner Public API Guide

**Audience:** AI agents and scripts acting on behalf of a verified WebPlanner user.

> **Before you create or update any project:** read this entire document and follow §5 (standards) and §8 (checklist).
>
> Give every agent: **(1) app base URL**, **(2) API token**, **(3) this guide URL**.

| | |
|---|---|
| Guide (this page) | `https://0.0.0.0:3000/docs/api` |
| Create token | Sign in → **Account → API Access** (`https://0.0.0.0:3000/account`) |
| Auth header | `Authorization: Bearer wp_…` |
| API base | `https://0.0.0.0:3000/api/v1` |

Version: 1.1 · Content-type: `text/markdown`

---

## 1. Capabilities

| Action | Endpoint |
|---|---|
| List projects (owned + shared) | `GET /api/v1/projects` |
| Create project (full sitemap + blocks) | `POST /api/v1/projects` |
| Read full project JSON | `GET /api/v1/projects/{id}` |
| Replace project JSON (last-writer-wins) | `PUT /api/v1/projects/{id}` |
| Delete project (owner only) | `DELETE /api/v1/projects/{id}` |

You act **as the token owner**. Plan limits (pages, blocks, storage) still apply.

Token management (browser session cookie — not Bearer):

- `GET` / `POST` `/api/account/api-keys`
- `DELETE` `/api/account/api-keys/{id}`

---

## 2. Authentication

```http
Authorization: Bearer wp_...
Content-Type: application/json
```

1. Tokens look like `wp_<random>`. Never log or echo the full token after first use.
2. Only **email-verified** users can create or use tokens.
3. `401` + `INVALID_API_KEY` → wrong, revoked, expired, or unverified user.
4. `403` + `PROJECT_LIMIT_EXCEEDED` / `PROJECT_CONTENT_LIMIT_EXCEEDED` → plan caps; reduce pages/blocks or ask the human to upgrade.
5. Do not invent endpoints outside `/api/v1/projects*` (and account key APIs for browsers).

---

## 3. Project JSON shape

```json
{
  "nodes": [ /* PageNode[] — sitemap tree */ ],
  "activeNodeId": "home",
  "rev": 0
}
```

### PageNode

| Field | Type | Req | Notes |
|---|---|---|---|
| id | string | yes | Unique, stable (slug or uuid). Never reuse. |
| parentId | string \| null | yes | `null` = root (homepage). |
| order | number | yes | 0-based among siblings. |
| title | string | yes | Canvas title. |
| description | string | no | Short purpose. |
| link | string | no | Public path, e.g. `/leistungen/elektro/`. |
| pageType | enum | no | `landing|product|blog|contact|about|pricing|privacy|terms|faq|gallery|service|custom` |
| color | string | no | Hex accent, e.g. `#0B3D5C`. |
| seo | object | no | `{ "metaTitle", "metaDescription" }` |
| pageStatus | enum | no | `pending|progress|completed` |
| blocks | WireframeBlock[] | yes | May be `[]`. |
| x, y | number | no | Optional; editor auto-layouts if omitted. |

### WireframeBlock

| Field | Type | Req | Notes |
|---|---|---|---|
| id | string | yes | Unique in project. |
| type | WireframeType | yes | Exact string from §4 (case-sensitive). |
| order | number | yes | 0 = top of page. |
| note | string | no | Editor label. |
| data | object | yes (recommended) | See below. |

Block `data` convention:

```json
{
  "backgroundColor": "#0B3D5C",
  "title": "Hero",
  "htmlContent": "<h1>…</h1><p>…</p>"
}
```

- Put **real client copy** in `htmlContent` (headings, lists, links).
- `title` = short section name shown on the canvas chip.
- Keep HTML simple; no scripts.

---

## 4. Allowed wireframe types

Use **only** these exact `type` values:

`Menu`, `Cover`, `Cover 2`, `Products`, `Carousel`, `Slider`, `Title`, `Title 2`, `Section`, `Article`, `Article 2`, `Article 3`, `Article 4`, `Content 1`, `Content 2`, `Content 3`, `Content 4`, `Cards`, `Cards 2`, `Footer`, `Footer 2`, `Footer 3`, `Links`, `Buttons`, `Button`, `Portfolio`, `Gallery`, `Chat`, `Form`, `Subscribe`, `Sign In`, `Contact Us`, `Pagination`, `Timeline`, `Faqs`, `Map`, `Map 2`, `Pricing`, `Table`, `Breadcrumbs`, `Breadcrumbs 2`, `Tabs`, `Features`, `Features 2`, `Video`, `Team`, `Product Card`, `Profile`, `Quote`, `Rating`, `Search`, `Dropdown`, `Audio`, `Bar Chart`, `Pie Chart`, `Line Chart`, `Block`, `Custom`

| Intent | Type |
|---|---|
| Site header | `Menu` — **first block** on full pages |
| Hero / H1 | `Cover` or `Cover 2` |
| KPIs / bullets | `Features`, `Features 2` |
| Service tiles | `Cards`, `Cards 2`, `Products` |
| Case studies | `Portfolio`, `Gallery` |
| Long section | `Article`, `Section`, `Content 1`–`4` |
| Process | `Timeline` |
| FAQ | `Faqs` |
| Contact / form | `Contact Us`, `Form` |
| Map | `Map` |
| CTAs | `Buttons`, `Button` |
| Team | `Team` |
| Site footer | `Footer` — **last block** on full pages |

---

## 5. Structure & content standards (MUST)

1. **One root** page with `parentId: null` (homepage).
2. **Tree = URL hierarchy** (parent → child matches folders/paths).
3. Set `link` when the brief has real paths.
4. **Menu first, Footer last** on every full website page:
   - `order: 0` → `Menu`
   - middle → content in reading order
   - **last** → `Footer`
   - Never put Footer immediately under Menu.
5. **One page = one purpose** when the brief asks for separate URLs.
6. Real copy in `htmlContent`, not only notes.
7. **SEO** on key pages: `metaTitle` ~50–60 chars, `metaDescription` ~120–160.
8. Open client questions → page `description`, HTML `<em>`, or `data.projectMeta`.
9. Use the **client language** for titles and body copy.
10. Stable unique `id`s (slugs like `elektro` are fine).
11. **Do not invent** phone numbers, legal claims, salaries — leave placeholders.

### 5b. Colors (MUST follow — blocks are invisible if white)

The canvas background is **white**. Blocks render as filled chips on that canvas.

| Rule | Detail |
|---|---|
| **Never use white** | Do **not** set `data.backgroundColor`, node `color`, or image placeholders to `#fff`, `#ffffff`, `white`, `rgb(255,255,255)`, or any near-white (e.g. `#fefefe`, `#f9f9f9`). White-on-white is invisible. |
| **Brand color wins** | If the brief names a brand color (hex, Pantone, “navy”, “brand blue”, logo colors), use **that** color for every block `data.backgroundColor` and every page `color` unless a section needs a deliberate accent. |
| **No brand given** | Use a **dark, readable** default: prefer `#0B3D5C`, `#1A3A5C`, `#1F2937`, or a mid brand-like blue/teal — not white, not pure black-only blocks if you can avoid it. |
| **Contrast** | Labels on blocks are white text — pick backgrounds dark enough to read (roughly luminance low; avoid pastel yellow/green unless the brand demands it). |
| **Consistency** | Same brand hex on `node.color` **and** block `data.backgroundColor` so the tree looks unified. |

Example when client brand is navy `#0B3D5C`:

```json
{
  "id": "home",
  "color": "#0B3D5C",
  "blocks": [
    {
      "id": "hero",
      "type": "Cover",
      "order": 0,
      "data": {
        "backgroundColor": "#0B3D5C",
        "title": "Hero",
        "htmlContent": "<h1>…</h1>"
      }
    }
  ]
}
```

---

## 6. HTTP examples

### Create

```bash
curl -sS -X POST "https://0.0.0.0:3000/api/v1/projects" \
  -H "Authorization: Bearer $WEBPLANNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Client site",
    "description": "Structure from brief",
    "data": {
      "nodes": [
        {
          "id": "home",
          "parentId": null,
          "order": 0,
          "title": "Home",
          "link": "/",
          "pageType": "landing",
          "blocks": [
            { "id": "nav", "type": "Menu", "order": 0,
              "data": { "backgroundColor": "#0B3D5C", "title": "Header", "htmlContent": "<nav>…</nav>" } },
            { "id": "hero", "type": "Cover", "order": 1,
              "data": { "backgroundColor": "#0B3D5C", "title": "Hero", "htmlContent": "<h1>…</h1>" } },
            { "id": "ft", "type": "Footer", "order": 2,
              "data": { "backgroundColor": "#0B3D5C", "title": "Footer", "htmlContent": "<footer>…</footer>" } }
          ]
        }
      ],
      "activeNodeId": "home"
    }
  }'
```

Success: **201** `{ id, name, nodes, nodesCount, … }`.  
Editor: `https://0.0.0.0:3000/project/{id}`

### Update / list / get / delete

```bash
# GET current tree first if you need it
curl -H "Authorization: Bearer $WEBPLANNER_API_KEY" "https://0.0.0.0:3000/api/v1/projects/$ID"

# PUT replaces data.nodes (LWW)
curl -X PUT -H "Authorization: Bearer $WEBPLANNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"data":{"nodes":[…],"activeNodeId":"home"}}' \
  "https://0.0.0.0:3000/api/v1/projects/$ID"

curl -H "Authorization: Bearer $WEBPLANNER_API_KEY" "https://0.0.0.0:3000/api/v1/projects"
curl -X DELETE -H "Authorization: Bearer $WEBPLANNER_API_KEY" "https://0.0.0.0:3000/api/v1/projects/$ID"
```

---

## 7. Errors

| Status | Meaning |
|---|---|
| 400 | Invalid JSON / missing name |
| 401 | Missing or invalid API key |
| 403 | Plan limit or not allowed |
| 404 | Project not found / no access |
| 405 | Method not allowed |
| 429 | Rate limited — back off and retry |
| 500 | Server error — retry with backoff |

Body: `{ "error": "…", "code": "OPTIONAL_CODE" }`

---

## 8. Agent checklist (before coding)

- [ ] Fetched and followed this guide (`https://0.0.0.0:3000/docs/api`)
- [ ] Valid `Bearer wp_…` for a verified user
- [ ] Understood brief (pages, language, open items)
- [ ] Designed tree: root + parents/children + `link` paths
- [ ] Unique `id` per node; correct `order` per sibling group
- [ ] **Menu first / Footer last** on full pages
- [ ] Real `htmlContent`; placeholders for unknown facts
- [ ] **No white / near-white block colors**; brand color on nodes + blocks when given
- [ ] SEO on key pages
- [ ] `POST /api/v1/projects` (or `PUT` after GET)
- [ ] Verified `GET /api/v1/projects/{id}` (counts + sample blocks)
- [ ] Returned editor URL to the human: `/project/{id}`

---

## 9. What the human gives the agent

Copy this to whoever runs the AI:

1. **Base URL** — e.g. `https://0.0.0.0:3000`
2. **API token** — from Account → API Access (shown once)
3. **This guide** — `https://0.0.0.0:3000/docs/api`

Suggested agent prompt:

> First fetch `https://0.0.0.0:3000/docs/api` and follow every rule. Then use the API token with `POST https://0.0.0.0:3000/api/v1/projects` to build the site from the brief below.

---

## 10. Out of scope (v1)

Collaborators, invitations, comments, presence, share links, billing, admin. Do not invent those endpoints.

---

*End of guide. Follow §5 on every project.*
