# AI Agent Guide: Product Addition & Google Merchant Center Integration

This guide provides instructions and schema specifications for autonomous AI agents (such as OpenClaw, LangChain/CrewAI agents, cron workers, or LLMs) to programmatically publish products to the **Nuho India** webstore.

Products created via this API are **automatically pushed in real time** to:
1. **Google Merchant Center (Content API v2.1)** for Google Shopping listings and Free Product Listings.
2. **Google Search Index (Google Indexing API)** for immediate URL crawling and indexing.
3. **Structured Data (Schema.org / JSON-LD)** embedded on the webstore for rich search snippets.

---

## 1. Authentication

All requests from AI agents must include an API Key in one of the following headers:

```http
x-api-key: YOUR_API_KEY
```

Alternative supported headers:
- `Authorization: Bearer YOUR_API_KEY`
- `api-key: YOUR_API_KEY`
- `x-agent-api-key: YOUR_API_KEY`

### Configuring Your Agent API Key
To protect your store, API keys must be kept private. You can configure your secret key via:
1. **Environment Variables**: Add `AGENT_API_KEY=your_secret_random_key_here` to your `.env` or server environment.
2. **Admin Settings / Database**: Set `AGENT_API_KEY` in the Admin Dashboard or PostgreSQL `SystemSetting` table.

> **Security Notice**: Never publish or expose your production API key. In all requests and examples below, replace `YOUR_AGENT_API_KEY` with your private secret key.

---

## 2. API Endpoints Overview

| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| **POST** | `/api/agents/products` | **Primary agent endpoint** to create a product. Returns agent-optimized JSON with Google sync status. | Yes (`x-api-key`) |
| **POST** | `/api/admin/products` | Standard admin endpoint to create a product. | Yes (`x-api-key` or Session) |
| **GET** | `/api/agents/products` | Retrieve machine-readable product catalog. (Free with `x-api-key`, requires x402 payment if unauthenticated). | Yes (`x-api-key` or x402) |
| **PUT** | `/api/admin/products` | Update an existing product by ID. Re-syncs to Google Merchant. | Yes (`x-api-key` or Session) |
| **DELETE**| `/api/admin/products?id={id}` | Delete a product. Automatically sends deletion request to Google Merchant Center & Google Indexing. | Yes (`x-api-key` or Session) |
| **POST** | `/api/upload` | Upload binary images (`type=image`) or 3D models (`type=model`) to S3/MinIO. | Optional / Form Data |

---

## 3. Product Schema & Attribute Reference

Below is the complete dictionary of all attributes accepted when creating a product, including how each field maps to **Google Merchant Center V2.1** and **Google Shopping**.

### Core Required Attributes

| Attribute | Type | Google Merchant Field | Description & Rules |
|---|---|---|---|
| `name` | `string` | `title` (max 150 chars) | **Required**. The title of the product.  <br>• *Best Practice*: `[Brand] + [Core Product] + [Material/Color] + [Key Spec]`.  <br>• *Google Rule*: Do NOT use ALL CAPS, emojis, or marketing words like "FREE SHIPPING", "BEST SALE", etc. |
| `sku` | `string` | `offerId` & `mpn` | **Required**. Unique Stock Keeping Unit (e.g. `NUHO-3D-PLANT-001`). Used by Google Merchant as the primary identifier. |
| `price` | `number` | `price` or `salePrice` | **Required**. Current selling price in INR (e.g. `499`).  <br>• If `originalPrice` is provided and greater than `price`, Google Merchant treats this as `salePrice` (creating a **Sale / Discount** badge). |

---

### Pricing & Inventory Attributes

| Attribute | Type | Google Merchant Field | Description |
|---|---|---|---|
| `originalPrice` | `number` | `price` (regular price) | *Optional*. MRP or regular pre-discount price in INR (e.g. `799`). Google Shopping uses this to display strikethrough pricing and percentage savings. |
| `priceUsd` | `number` | Internal / Currency | *Optional*. Price in USD for international customers or cross-border AI agents. |
| `inStock` | `boolean` | `availability` | *Optional* (default: `true`). Maps to Google `in stock` when `true`, and `out of stock` when `false`. |
| `stockCount` | `number` | Internal | *Optional* (default: `0`). Quantity of physical items in stock. |
| `trackStock` | `boolean` | Internal | *Optional* (default: `true`). Whether to auto-decrement stock when orders are placed. |
| `lowStockThreshold`| `number` | Internal | *Optional* (default: `5`). Threshold below which low-stock notifications fire. |
| `maxQuantityPerOrder` | `number` | Internal | *Optional*. Maximum units a single customer can buy per order. |

---

### Category & Google Taxonomy Attributes

| Attribute | Type | Google Merchant Field | Description |
|---|---|---|---|
| `category` | `string` | `productTypes` | *Optional* (default: `'UNCATEGORIZED'`). Main category name (e.g. `"Home Decor"`). Automatically registered in webstore navigation. |
| `subCategory` | `string` | `productTypes` | *Optional*. Sub-category name (e.g. `"Planters"`). Mapped to Google as `"Home Decor > Planters"`. |
| `googleProductCategory` | `string` or `number` | `googleProductCategory` | *Recommended*. Google's official taxonomy classification (e.g. `"Home & Garden > Lawn & Garden > Gardening > Pots & Planters"` or ID `3528`). Improves Google Shopping ad targeting and discoverability. |

---

### Product Identifiers & Brand Attributes

| Attribute | Type | Google Merchant Field | Description & Rules |
|---|---|---|---|
| `brand` | `string` | `brand` | *Optional* (default: `'Nuho India'`). The brand name. |
| `gtin` | `string` | `gtin` | *Optional*. Global Trade Item Number (UPC, EAN, JAN, ISBN). Required for commercial off-the-shelf items. |
| `mpn` | `string` | `mpn` | *Optional*. Manufacturer Part Number. If omitted, falls back to `sku`. |
| `condition` | `string` | `condition` | *Optional* (default: `'new'`). Must be one of: `'new'`, `'refurbished'`, `'used'`. |

> **Custom / 3D Printed Goods (`identifierExists`)**:  
> If an AI agent does not provide a `gtin` or `mpn`, Nuho India's sync engine **automatically sets `identifierExists: false`** in the Google Merchant feed. This allows custom manufactured and 3D-printed items to be approved without triggering missing GTIN disapprovals.

---

### Manufacturing, Physical Specs & Shipping Attributes

| Attribute | Type | Google Merchant Field | Description |
|---|---|---|---|
| `weight` | `number` | `shippingWeight` | *Optional* (default: `200`). Weight in **grams** (e.g. `250` for 250g).  <br>• *Automatic Conversion*: Nuho's Google sync engine divides grams by 1000 and sends `shippingWeight: { value: "0.250", unit: "kg" }` to Google for automated carrier shipping rate calculations. |
| `material` | `string` | `material` | *Optional* (default: `'PLA+ Plastic'`). Material used (e.g. `"PLA+ Bioplastic"`, `"PETG"`, `"Carbon Fiber"`, `"Vinyl"`, `"Resin"`). |
| `color` | `string` | `color` | *Optional*. Primary color (e.g. `"Matte Black"`, `"Emerald Green"`, `"White"`). |

---

### Media & Visual Attributes

| Attribute | Type | Google Merchant Field | Description & Rules |
|---|---|---|---|
| `images` | `string[]` | `imageLink` & `additionalImageLinks` | Array of direct, publicly accessible image URLs.  <br>• `images[0]` is the primary image (`imageLink`).  <br>• `images.slice(1)` are secondary images (`additionalImageLinks`).  <br>• *Google Rules*: Minimum 800x800 px, clear lighting, no promotional watermarks or discount badges on the image. |
| `model3d` | `string` | Internal (3D Viewer) | Public URL to `.glb` or `.gltf` 3D file. Renders interactive Three.js 3D viewer on webstore product page. |
| `videoUrl` | `string` | Internal | Optional video demonstration URL (e.g. YouTube, MP4, Vimeo). |

---

### Content, SEO & Digital Goods

| Attribute | Type | Google Merchant Field | Description |
|---|---|---|---|
| `description` | `string` | `description` (max 5000 chars) | Detailed description of the product. Explain dimensions, manufacturing technique, care instructions, and what's in the box. |
| `slug` | `string` | `link` | Optional URL slug (e.g. `"geometric-cyber-planter"`). If omitted, auto-generated from `name`. Webstore URL becomes `https://nuho.in/products/{slug}`. |
| `tags` | `string[]` or CSV `string` | Internal Search / SEO | Keywords for search and internal catalog filtering (e.g. `["planter", "cyberpunk", "home decor"]`). |
| `isDigital` | `boolean` | Internal | Set `true` if this product is a digital download (e.g. STL file). |
| `digitalFileUrl` | `string` | Internal | Protected download link for digital products. |
| `isVisible` | `boolean` | Sync Controller | Default: `true`. **If set to `false`, the product is omitted from the store and automatically deleted from Google Merchant Center and Google Search Index.** |

---

### Customization & Tiered Pricing (Advanced)

#### `customizationOptions` (JSON Object)
For products that allow customer personalization (e.g. custom stickers, custom 3D prints, custom engravings):

```json
{
  "enabled": true,
  "allowImageUpload": true,
  "allowTextEngraving": true,
  "maxTextLength": 30,
  "colorChoices": ["Matte Black", "Arctic White", "Crimson Red"],
  "variants": [
    { "name": "Small (10cm)", "priceModifier": 0 },
    { "name": "Medium (15cm)", "priceModifier": 150 },
    { "name": "Large (20cm)", "priceModifier": 300 }
  ]
}
```

#### `tieredPricing` (JSON Array)
For bulk / wholesale pricing:

```json
[
  { "minQty": 5, "price": 449 },
  { "minQty": 20, "price": 399 },
  { "minQty": 50, "price": 349 }
]
```

---

## 4. Uploading Media Assets (`POST /api/upload`)

Before creating a product, your agent can upload images or 3D models directly to the webstore's storage.

### Request (`multipart/form-data`)
- `file`: The binary file (JPEG, PNG, WebP, SVG, GLB, GLTF).
- `type`: `'image'` for photos, or `'model'` for 3D `.glb`/`.gltf` files.

### Response
```json
{
  "success": true,
  "publicUrl": "https://nuho.in/uploads/1740000000_photo.webp",
  "filename": "1740000000_photo.webp",
  "size": 142080
}
```
Use the returned `publicUrl` directly in the `images` or `model3d` array of your product creation request.

---

## 5. Complete JSON Payload Example

```json
{
  "name": "Geometric Cyberpunk Planter (Matte Black)",
  "sku": "NUHO-3D-PLANT-001",
  "price": 649,
  "originalPrice": 999,
  "priceUsd": 12.99,
  "category": "Home Decor",
  "subCategory": "Planters",
  "googleProductCategory": "Home & Garden > Lawn & Garden > Gardening > Pots & Planters",
  "description": "Premium hexagonal geometric succulent planter 3D printed with high-grade eco-friendly PLA+ matte black bioplastic. Features built-in drainage holes and matching saucer tray. Dimensions: 12cm x 12cm x 10cm.",
  "brand": "Nuho India",
  "condition": "new",
  "material": "PLA+ Matte Bioplastic",
  "color": "Obsidian Black",
  "weight": 280,
  "inStock": true,
  "stockCount": 35,
  "trackStock": true,
  "lowStockThreshold": 5,
  "images": [
    "https://nuho.in/uploads/planter-primary.webp",
    "https://nuho.in/uploads/planter-angle-view.webp",
    "https://nuho.in/uploads/planter-scale-view.webp"
  ],
  "model3d": "https://nuho.in/uploads/geometric-planter.glb",
  "tags": [
    "planter",
    "succulent",
    "cyberpunk",
    "home decor",
    "3d printed",
    "minimalist"
  ],
  "customizationOptions": {
    "enabled": false
  }
}
```

---

## 6. Code Examples for AI Agents

### cURL

```bash
curl -X POST https://nuho.in/api/agents/products \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -d '{
    "name": "Geometric Cyberpunk Planter",
    "sku": "NUHO-3D-PLANT-001",
    "price": 649,
    "originalPrice": 999,
    "category": "Home Decor",
    "subCategory": "Planters",
    "googleProductCategory": "Home & Garden > Lawn & Garden > Gardening > Pots & Planters",
    "description": "Hexagonal succulent planter crafted from matte PLA+.",
    "material": "PLA+ Matte Bioplastic",
    "color": "Obsidian Black",
    "weight": 280,
    "inStock": true,
    "stockCount": 20,
    "images": ["https://nuho.in/uploads/planter-primary.webp"]
  }'
```

### Node.js / TypeScript

```typescript
interface CreateProductPayload {
  name: string
  sku: string
  price: number
  originalPrice?: number
  category?: string
  subCategory?: string
  googleProductCategory?: string
  description?: string
  brand?: string
  color?: string
  material?: string
  weight?: number // in grams
  inStock?: boolean
  stockCount?: number
  images?: string[]
  model3d?: string
  tags?: string[]
}

async function addProductToNuho(product: CreateProductPayload, apiKey: string) {
  const response = await fetch('https://nuho.in/api/agents/products', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': apiKey
    },
    body: JSON.stringify(product)
  })

  if (!response.ok) {
    const errorData = await response.json()
    throw new Error(`Failed to add product: ${JSON.stringify(errorData)}`)
  }

  const result = await response.json()
  console.log(`Product created! Webstore URL: ${result.data.url}`)
  console.log(`Google Merchant Sync: ${result.syncStatus.googleMerchantCenter}`)
  return result
}
```

### Python (3.9+)

```python
import requests

def add_product(product_data: dict, api_key: str):
    url = "https://nuho.in/api/agents/products"
    headers = {
        "Content-Type": "application/json",
        "x-api-key": api_key
    }
    
    response = requests.post(url, json=product_data, headers=headers)
    
    if response.status_code == 201:
        data = response.json()
        print("Success!", data["message"])
        print("Live URL:", data["data"]["url"])
        print("Google Merchant Sync Status:", data["syncStatus"]["googleMerchantCenter"])
        return data
    else:
        print("Error:", response.status_code, response.text)
        response.raise_for_status()

# Example usage
new_product = {
    "name": "Cyberpunk Desk Organizer",
    "sku": "NUHO-DESK-ORG-01",
    "price": 549,
    "originalPrice": 899,
    "category": "Office",
    "subCategory": "Desk Accessories",
    "googleProductCategory": "Office Supplies > Desk Accessories > Desk Organizers",
    "description": "Modular 3D printed desk organizer with card slots and pen holders.",
    "brand": "Nuho India",
    "material": "PLA+ Bioplastic",
    "color": "Gunmetal Grey",
    "weight": 220,
    "inStock": True,
    "stockCount": 15,
    "images": ["https://nuho.in/uploads/desk-organizer.webp"],
    "tags": ["desk", "organizer", "office", "3d-printed"]
}

# add_product(new_product, "YOUR_AGENT_API_KEY")
```

---

## 7. HTTP Response Codes

| Status Code | Meaning | Cause |
|---|---|---|
| **201 Created** | Product successfully stored and queued for Google sync | Valid request. Product ID and live URL returned. |
| **400 Bad Request** | Validation failed | Missing required fields (`name`, `price`, or `sku`), or malformed JSON. |
| **401 Unauthorized** | Authentication failed | Missing or invalid `x-api-key` header. |
| **500 Server Error** | Internal failure | Database or server exception. Error details returned in `error` field. |

---

## 8. Automated Google Merchant & Search Sync Behavior

When an AI agent creates or updates a product:
1. **Google Indexing API**: Sends a notification to Google Search crawlers for `https://nuho.in/products/{slug}` with action `URL_UPDATED`.
2. **Google Merchant Center API v2.1**: Directly inserts or updates the product payload in your Merchant Center account.
   - If `isVisible: true`: Upserted to Google Merchant.
   - If `isVisible: false` or deleted: Automatically sent to Google Merchant API with `products.delete()` to ensure no out-of-stock or removed products trigger policy violations.
