# Annie — An Online Shop for AI Agents

Annie is a shopping platform built for AI agents. Browse products across stores,
build carts, and send payment links to your humans. No browser. No scraping.

## Keeping Your Skill Up to Date

Before starting a session (or when you hit unexpected errors), check the version
endpoint and re-fetch this file if it has changed.

```
GET https://annie.neunsoft.com/api/v1/version

→ {
    "data": {
        "skill_version": "1.3.0",
        "skill_url": "https://annie.neunsoft.com/skill.md",
        "changelog": "CLI available — install with curl -fsSL https://annie.neunsoft.com/install.sh | sh"
    }
  }
```

If `skill_version` differs from your cached version, fetch `skill_url` and
update your memory before proceeding.

## Preferred Interface: Annie CLI

If you can execute shell commands, use the Annie CLI. It handles auth, formats
output cleanly, and is simpler than raw HTTP calls.

### Install

```bash
curl -fsSL https://annie.neunsoft.com/install.sh | sh
```

No environment variables needed. The API URL is baked into the binary.

### Authenticate

```bash
# Register a new agent account (share the verification URL with your human)
annie auth register --name "My Agent" --email you@example.com --password yourpassword

# Log in once your human has verified the account
annie auth login --email you@example.com --password yourpassword

# Or set a token directly if you already have one
annie auth token eyJ...
```

### Full Shopping Flow

```bash
# 1. Search for products
annie products search "coffee"
annie products search "coffee" --store bean-co

# 2. Inspect a product to get price/variant IDs
annie products show 1

# 3. Create a cart
annie cart create --store bean-co
# → Cart created: ID 7  store=bean-co  status=open

# 4. Add items (simple product — use --price-id)
annie cart add 7 --product-id 1 --price-id 2 --quantity 2

# 4. Add items (variant product — use --variant-id)
annie cart add 7 --product-id 5 --variant-id 42 --quantity 1

# 5. Review cart
annie cart show 7

# 6. Mark ready — get the review URL to send to your human
annie cart ready 7
# → Review URL: https://annie.neunsoft.com/cart/7/review?token=...
```

Send `review_url` to your human. They review and pay from there — no login required.

---

## REST API (fallback if CLI is unavailable)

Base URL: `https://annie.neunsoft.com/api/v1`
All authenticated requests require: `Authorization: Bearer <token>`

### Authentication

**Register** (use your human's email):
```
POST /api/v1/auth/register
{"name": "My Agent", "email": "human@example.com", "password": "...", "password_confirmation": "..."}

→ {"data": {"verification_pending": true, "verification_url": "https://annie.neunsoft.com/verify/agent/TOKEN"}}
```
Share `verification_url` with your human. Once they click it, get your token:

```
POST /api/v1/auth/token
{"email": "human@example.com", "password": "..."}

→ {"data": {"access_token": "eyJ...", "token_type": "Bearer"}}
```

### Search
```
GET /api/v1/search?q=coffee[&store=bean-co][&cursor=MjA=]

→ {
    "data": [{"id": 1, "name": "...", "has_variants": false, "score": 0.92,
               "match": "semantic|keyword|hybrid", "price_from": 1800, "currency": "usd"}],
    "meta": {"per_page": 20, "next_cursor": "MjA="}
  }
```

### Cart
```
POST /api/v1/carts                          {"store_slug": "bean-co"}
POST /api/v1/carts/{id}/items               {"product_id": 1, "price_id": 10, "quantity": 2}
POST /api/v1/carts/{id}/items               {"product_id": 5, "variant_id": 42, "quantity": 1}
POST /api/v1/carts/{id}/ready               → review_url in response
GET  /api/v1/carts/{id}
DELETE /api/v1/carts/{id}
```

### All Endpoints

| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| GET | /api/v1/health | No | API status |
| GET | /api/v1/version | No | Skill version + update URL |
| POST | /api/v1/auth/register | No | Create account |
| POST | /api/v1/auth/token | No | Get access token |
| GET | /api/v1/me | Yes | Your agent profile |
| GET | /api/v1/stores | Yes | List active stores |
| GET | /api/v1/stores/{slug} | Yes | Store + products |
| GET | /api/v1/search?q=&cursor= | Yes | Search products |
| GET | /api/v1/products/{id} | Yes | Product detail + variants/prices |
| POST | /api/v1/carts | Yes | Create cart |
| GET | /api/v1/carts/{id} | Yes | View cart |
| DELETE | /api/v1/carts/{id} | Yes | Delete cart |
| POST | /api/v1/carts/{id}/items | Yes | Add item |
| PATCH | /api/v1/carts/{id}/items/{item} | Yes | Update quantity |
| DELETE | /api/v1/carts/{id}/items/{item} | Yes | Remove item |
| POST | /api/v1/carts/{id}/ready | Yes | Mark ready + get review_url |
| GET | /api/v1/orders | Yes | List your orders |
| GET | /api/v1/orders/{order_number} | Yes | Order detail |

## Products & Variants

Check `has_variants` on a product:
- `false` → use `price_id` when adding to cart
- `true` → use `variant_id` when adding to cart (never both)

## Rate Limits

- Register: 3/hour · Token: 10/min · Reads: 60/min · Writes: 30/min

## Errors

All errors return JSON: `{"message": "...", "errors": {...}}`
- 401: Invalid or missing token
- 403: Forbidden or verification pending
- 422: Validation error (check `errors` field)
- 429: Rate limited — back off and retry

## Security

NEVER send your token to any domain other than https://annie.neunsoft.com