# SiteSpawn AiCMS API Version 0.5.18

> REST API for Site. All endpoints return JSON. Base URL: https://sitespawn.ai
>
> **Important:** All API requests must be made to your own site's domain (e.g. https://yoursite.com/api/...). This documentation is hosted on sitespawn.ai but the API lives on each individual site.

## Authentication

Create an account and log in to obtain an access token. Pass it as a Bearer token in the Authorization header for authenticated endpoints.

- **Register:** POST /api/auth/register — Body: {"email", "password", "name"}
- **Login:** POST /api/auth/login — Body: {"email", "password"}
- **Refresh:** POST /api/auth/refresh
- **Logout:** POST /api/auth/logout
- **Profile:** GET /api/auth/me (auth required)
- **Update profile:** PUT /api/auth/profile (auth required)
- **Change password:** PUT /api/auth/change-password (auth required)

## Public Endpoints

No authentication required.

### Shop

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/shop/products | List published products. Params: category, tag, page, limit |
| GET | /api/shop/products/{sku} | Get product by SKU |
| GET | /api/shop/bundles | List product bundles |
| GET | /api/shop/bundles/{sku} | Get bundle by SKU |
| GET | /api/shop/reviews/{sku} | Get approved reviews for a product |

### Content

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/content/posts | List published blog posts. Params: category, tag, page, limit |
| GET | /api/content/posts/{slug} | Get blog post by slug |
| GET | /api/content/pages/{slug} | Get CMS page by slug |
| GET | /api/content/categories | List content categories |
| GET | /api/content/tags | List content tags |
| GET | /feed.xml | RSS feed of blog posts |

### Forum

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/forum/categories | List forum categories |
| GET | /api/forum/stats | Forum statistics |
| GET | /api/forum/categories/{slug}/topics | List topics in a category. Params: sort (latest, popular, unanswered), page, limit |
| GET | /api/forum/topics/{id} | Get topic with replies |

### Other

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/faq/categories | FAQ categories with entries |
| GET | /api/faq/search?q={query} | Search FAQ |
| GET | /api/menu?name=main | Navigation menu tree |
| POST | /api/contact | Contact form. Body: {"name", "email", "subject", "message"} |

## Authenticated Endpoints

Require Authorization: Bearer {token} header.

### Cart & Checkout

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/cart | Get shopping cart |
| POST | /api/cart/items | Add item. Body: {"product_id", "quantity"} or {"bundle_id", "quantity"} |
| PUT | /api/cart/items/{id} | Update quantity. Body: {"quantity"} |
| DELETE | /api/cart/items/{id} | Remove item |
| POST | /api/cart/coupon | Apply coupon. Body: {"code"} |
| DELETE | /api/cart/coupon | Remove coupon |
| POST | /api/checkout | Create order from cart. Body: shipping address fields |

### Orders

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/orders | List user's orders |
| GET | /api/orders/{id} | Get order details |
| GET | /api/orders/{number}/invoice | Download invoice PDF |

### Tickets

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/tickets | List user's tickets |
| POST | /api/tickets | Create ticket. Body: {"subject", "message"} |
| GET | /api/tickets/{id} | Get ticket with comments |
| POST | /api/tickets/{id}/comments | Add comment. Body: {"body"} |

### Forum (authenticated)

| Method | Path | Description |
|--------|------|-------------|
| POST | /api/forum/topics | Create topic. Body: {"category_id", "title", "body_markdown"} |
| POST | /api/forum/topics/{id}/replies | Reply. Body: {"body_markdown"} |
| POST | /api/forum/topics/{id}/vote | Vote. Body: {"value": 1 or -1} |
| PUT | /api/forum/topics/{id}/solved | Mark solved |

### Reviews

| Method | Path | Description |
|--------|------|-------------|
| POST | /api/reviews/create | Submit review. Body: {"product_sku", "rating", "title", "body"} |
| GET | /api/reviews/reviewable | Products available to review (purchased) |

## Admin Endpoints

Require admin role. Pass Authorization: Bearer {token} header.

### Products (Admin)

Full replace semantics: PUT requires all fields. Always GET first, modify what you need, then PUT the full object.

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/admin/products | List all products. Returns id, sku, name, price, currency, status, stock_status |
| POST | /api/admin/products | Create product. Body: {"sku", "name", "price", "short_description", "description", "compare_at_price", "status", "stock_status", "weight", "length", "width", "height", "category", "tags", "nss_product_id", "specs_html", "gallery_html", "cover_image_url"} |
| GET | /api/admin/products/{id} | Get full product detail including all fields |
| PUT | /api/admin/products/{id} | Full replace update — send complete product object |
| DELETE | /api/admin/products/{id} | Delete product |

Product field reference:
- status: draft, published, archived
- stock_status: in_stock, out_of_stock, preorder
- price / compare_at_price: string (e.g. "99.00")
- weight / length / width / height: float (kg / cm)
- nss_product_id: integer — links to NextSmartShip product
- specs_html / gallery_html: raw HTML blobs for product page sections
- tags: array of strings

### Content Translations

Create locale-tagged draft copies of content and optionally auto-translate via translate.sitespawn.ai. All copies are created as drafts/disabled with source-language content pre-filled.

| Method | Path | Description |
|--------|------|-------------|
| POST | /api/admin/content/posts/{id}/translate | Copy a blog post to a new locale. Body: {"locale": "de"} |
| POST | /api/admin/content/pages/{id}/translate | Copy a page to a new locale. Body: {"locale": "de"} |
| POST | /api/admin/faq/{id}/translate | Copy a FAQ entry to a new language. Body: {"language": "de"} |
| POST | /api/admin/menu/translate | Copy a menu to a new locale. Body: {"menu": "main", "locale": "de"} |
| POST | /api/admin/forms/{id}/translate | Copy a form to a new locale. Body: {"locale": "de"} |
| PUT | /api/admin/menu/item | Update a menu item. Body: {"id": 42, "title": "New", "url": "/new/", "target": "_blank"}. Lookup by id or {"lookup_url": "/old/", "menu_name": "main"}. URL changes cascade to translations. |
| POST | /api/admin/menu/item | Add a menu item. Body: {"menu_name": "main", "item": {...}, "under_url": "/parent/"}. Cascades to translated menus. |
| DELETE | /api/admin/menu/item/delete?id=42 | Delete a menu item by ID. Also: ?url=/path/&menu=main. Cascades to translations. |

Menu item IDs are stable — they do not change when other items are added or removed.

Supported locales: en, de, fr, es, pt, ja, zh, yue, hi, ar, ru

All translate endpoints are idempotent — re-running returns the existing translation if one already exists for that locale.

### Palette Management

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/admin/palette/state | Get current palette state (source, name, colors) |
| GET | /api/admin/palette/catalog | List available hub palettes |
| POST | /api/admin/palette/activate/{id} | Activate a hub palette by ID |
| POST | /api/admin/palette/deactivate | Deactivate the current palette |
| POST | /api/admin/palette/save-custom | Save current palette as a custom snapshot |
| POST | /api/admin/palette/restore-custom | Restore the saved custom snapshot |

### Bulk Site Translation

| Method | Path | Description |
|--------|------|-------------|
| POST | /api/admin/ai/translate-site | Translate entire site to a locale. Body: {"locale", "force", "stale_only"}. Returns SSE stream with progress events (start, progress, translated, skipped, failed, done) |

### Language Settings

Language management uses the shop settings API:

- **default_language** — the site's default locale code (e.g. "en")
- **supported_locales** — comma-separated list of enabled locale codes (e.g. "en,de,fr")

Use GET/PUT /api/admin/shop/settings to read and update these values.

### Ticket Management (Admin)

| Method | Path | Description |
|--------|------|-------------|
| GET | /api/admin/tickets | List all tickets. Params: status, sort |
| GET | /api/admin/tickets/{id} | Get ticket with comments |
| POST | /api/admin/tickets/{id}/comments | Add comment. Body: {"body", "is_internal"} |
| PUT | /api/admin/tickets/{id} | Update ticket. Body: {"status"} or {"priority"} or {"category_id"} |
| PUT | /api/admin/tickets/{id}/assign | Assign ticket. Body: {"assigned_to": user_id} (0 to unassign) |
| GET | /api/admin/ticket-categories | List ticket categories |

Status values: open, in_progress, waiting, resolved, closed
Priority values: low, normal, high, urgent

### AI Assistant (Admin)

| Method | Path | Description |
|--------|------|-------------|
| POST | /api/admin/ai/chat | Chat with AI. Body: {"context_type", "message", "session_id", "context_id", "context_filename"}. Returns: {"session_id", "reply", "content_updated", "content_deleted", "content_id"} |
| GET | /api/admin/ai/context/{type} | List available context items for a type (post, page, faq, product, css, media) |
| GET | /api/admin/ai/sessions | List AI sessions. Params: context_type |
| POST | /api/admin/ai/image/generate | Generate image. Body: {"prompt", "model", "aspect_ratio", "alt_text", "save_to_library"} |

The AI assistant can create, edit, and delete content via natural language instructions. Use context_type to specify what content to work with and context_id to target a specific item.
