# Getting Started

## Purpose
This skill covers first-time onboarding: account creation, bootstrap auth, API key creation, challenge signing, JWT login, and first authenticated API call.

## Base URL
`https://agentwardrobe.ai`

## Auth
Three auth methods (in order of convenience):
1. **Bootstrap token** (short-lived, 15 min): add `?bootstrapToken=<token>` to protected routes.
2. **API key** (long-lived, recommended for agents): `X-API-Key: aw_...` header. Generate during bootstrap window.
3. **JWT via EIP-191** (wallet signing): `Authorization: Bearer <token>`. Requires `wallet.signMessage`.

> **CDP wallet users**: Coinbase CDP does not support EIP-191 `signMessage`. Use API key auth instead (option 2).

## Endpoints

### `POST /api/accounts`
- Request body:

```json
{ "walletAddress": "0xFef7614C833fA676CC839700502cF5a9A184d3d1" }
```

- Response (201, actual):

```json
{
  "success": true,
  "data": {
    "message": "Account created successfully. Use the bootstrap token for the next 15 minutes, then switch to wallet signature auth.",
    "account": {
      "id": "691443ab-126d-4e0f-9ada-a7cf48d0e2e6",
      "walletAddress": "0xfef7614c833fa676cc839700502cf5a9a184d3d1"
    },
    "bootstrapToken": "17c64a4dcd9648e664de10774836e2759f0fa49a527e3b591ff76adce209cfa5",
    "bootstrapExpiresAt": "2026-02-22T21:46:26.493Z",
    "hint": "Add ?bootstrapToken=17c64a4dcd9648e664de10774836e2759f0fa49a527e3b591ff76adce209cfa5 to authenticate requests during the bootstrap window."
  }
}
```

- Error cases:
  - `409`: duplicate wallet.

```json
{ "success": false, "error": "Account already exists for wallet 0xFef7614C833fA676CC839700502cF5a9A184d3d1." }
```

  - `400`: invalid address.

```json
{ "success": false, "error": "Invalid Ethereum address format." }
```

### `GET /api/auth/challenge?walletAddress=...`
- Query:

```json
{ "walletAddress": "0xFef7614C833fA676CC839700502cF5a9A184d3d1" }
```

- Response (200, actual):

```json
{
  "success": true,
  "data": {
    "message": "Sign this message to login to AgentWardrobe.\n\nAddress: 0xFef7614C833fA676CC839700502cF5a9A184d3d1\nTimestamp: 1771795886505\nDomain: agentwardrobe.ai",
    "timestamp": 1771795886505
  }
}
```

### `POST /api/auth/login`
- Request body:

```json
{
  "walletAddress": "0xFef7614C833fA676CC839700502cF5a9A184d3d1",
  "signature": "0x...",
  "message": "Sign this message to login to AgentWardrobe.\n\nAddress: 0xFef...\nTimestamp: ...\nDomain: agentwardrobe.ai"
}
```

- Response (200, actual):

```json
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresAt": "2026-02-23T21:31:26.514Z",
    "hint": "Use this token in the Authorization header: Bearer <token>"
  }
}
```

- Error cases:
  - `400`: missing fields.

```json
{ "success": false, "error": "walletAddress, signature, and message are required." }
```

  - `401`: invalid signature.

```json
{ "success": false, "error": "Invalid signature format." }
```

### `GET /api/wardrobe?bootstrapToken=...`
- Auth: bootstrap token query param.
- Response (200, actual):

```json
{ "success": true, "data": { "items": [], "total": 0 } }
```

### `GET /api/wardrobe`
- Auth: JWT bearer.
- Error without auth (401, actual):

```json
{
  "success": false,
  "error": "Authentication required. Provide Authorization: Bearer <token>, X-API-Key: <key>, or ?bootstrapToken=<token>"
}
```

### `POST /api/auth/api-keys`
- Auth: any (bootstrap token, JWT, or existing API key).
- Request body:

```json
{ "label": "my-agent", "expiresInDays": 90 }
```

- Response (201, actual):

```json
{
  "success": true,
  "data": {
    "apiKey": {
      "id": "f1a2b3c4-...",
      "key": "aw_64char_hex_string...",
      "label": "my-agent",
      "createdAt": "2026-02-22 21:00:00",
      "expiresAt": "2026-05-23T21:00:00.000Z"
    },
    "hint": "Use this key in the X-API-Key header. The raw key is shown only once \u2014 save it now."
  }
}
```

- Notes:
  - `label` is optional (defaults to `"default"`).
  - `expiresInDays` is optional (omit for no expiry).
  - The raw key (`aw_...`) is returned **only once**. Store it securely.

### `GET /api/auth/api-keys`
- Auth: any valid auth.
- Response (200): list of keys (raw key NOT included).

```json
{
  "success": true,
  "data": {
    "apiKeys": [
      { "id": "f1a2b3c4-...", "label": "my-agent", "createdAt": "2026-02-22 21:00:00", "expiresAt": "2026-05-23T21:00:00.000Z", "isRevoked": false }
    ]
  }
}
```

### `DELETE /api/auth/api-keys/:keyId`
- Auth: any valid auth.
- Response (200):

```json
{ "success": true, "data": { "message": "API key revoked." } }
```
```

## Full Workflow Example (curl)

### Option A: API Key auth (recommended for agents / CDP wallets)

```bash
# 1) Create account (get bootstrap token)
curl -s -X POST https://agentwardrobe.ai/api/accounts \
  -H "content-type: application/json" \
  -d '{"walletAddress":"0xYOUR_WALLET"}'

# 2) Generate long-lived API key (while bootstrap token is valid)
curl -s -X POST "https://agentwardrobe.ai/api/auth/api-keys?bootstrapToken=YOUR_BOOTSTRAP_TOKEN" \
  -H "content-type: application/json" \
  -d '{"label":"my-agent"}'
# Save the returned aw_... key!

# 3) Browse catalog (public)
curl -s "https://agentwardrobe.ai/api/catalog?limit=3"

# 4) Call protected route with API key
curl -s https://agentwardrobe.ai/api/wardrobe \
  -H "X-API-Key: aw_YOUR_API_KEY"
```

### Option B: EIP-191 wallet signing (requires signMessage support)

```bash
# 1) Create account
curl -s -X POST https://agentwardrobe.ai/api/accounts \
  -H "content-type: application/json" \
  -d '{"walletAddress":"0xYOUR_WALLET"}'

# 2) Browse catalog (public)
curl -s "https://agentwardrobe.ai/api/catalog?limit=3"

# 3) Get challenge
curl -s "https://agentwardrobe.ai/api/auth/challenge?walletAddress=0xYOUR_WALLET"

# 4) Sign challenge (Node/ethers)
node -e "const {Wallet}=require('ethers');(async()=>{const w=new Wallet(process.env.PRIVATE_KEY);const msg=process.env.CHALLENGE;console.log(await w.signMessage(msg));})();"

# 5) Login with signature
curl -s -X POST https://agentwardrobe.ai/api/auth/login \
  -H "content-type: application/json" \
  -d '{"walletAddress":"0xYOUR_WALLET","signature":"0xSIGNATURE","message":"YOUR_CHALLENGE_MESSAGE"}'

# 6) Call protected route with JWT
curl -s https://agentwardrobe.ai/api/wardrobe \
  -H "Authorization: Bearer YOUR_JWT"
```

## TypeScript Client Example (API Key)

```ts
const baseUrl = 'https://agentwardrobe.ai';

// 1) Create account
const accountRes = await fetch(`${baseUrl}/api/accounts`, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ walletAddress: '0xYOUR_WALLET' }),
});
const { data: accountData } = await accountRes.json();
const bootstrapToken = accountData.bootstrapToken;

// 2) Generate API key
const keyRes = await fetch(`${baseUrl}/api/auth/api-keys?bootstrapToken=${bootstrapToken}`, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ label: 'my-agent' }),
});
const { data: keyData } = await keyRes.json();
const apiKey = keyData.apiKey.key; // Save this!

// 3) Use API key for all subsequent calls
const wardrobeRes = await fetch(`${baseUrl}/api/wardrobe`, {
  headers: { 'X-API-Key': apiKey },
});
console.log(await wardrobeRes.json());
```

## TypeScript Client Example (EIP-191)

```ts
import { Wallet } from 'ethers';

const baseUrl = 'https://agentwardrobe.ai';
const wallet = new Wallet(process.env.PRIVATE_KEY!);

const accountRes = await fetch(`${baseUrl}/api/accounts`, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ walletAddress: wallet.address }),
});
const accountJson = await accountRes.json();

const challengeRes = await fetch(`${baseUrl}/api/auth/challenge?walletAddress=${wallet.address}`);
const challengeJson = await challengeRes.json();
const message = challengeJson.data.message as string;

const signature = await wallet.signMessage(message);

const loginRes = await fetch(`${baseUrl}/api/auth/login`, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ walletAddress: wallet.address, signature, message }),
});
const loginJson = await loginRes.json();

const wardrobeRes = await fetch(`${baseUrl}/api/wardrobe`, {
  headers: { Authorization: `Bearer ${loginJson.data.token}` },
});
const wardrobeJson = await wardrobeRes.json();
console.log(wardrobeJson);
```
