# 마켓파일럿 AI 주문 API

마켓파일럿(www.marketpilot.it)의 마케팅 상품을 AI 에이전트가 직접 조회·견적·주문하고,
주문 진행 상황과 포인트를 관리할 수 있는 API예요.

- REST Base URL: `https://api.marketpilot.it/v1/ai`
- MCP Server URL: `https://api.marketpilot.it/mcp` (Streamable HTTP)
- OpenAPI 스펙: `https://api.marketpilot.it/v1/ai/openapi.json`

## 공개 카탈로그 (인증 불필요)

서비스·상품을 추천하거나 살펴보는 용도라면 API 키 없이 아래를 바로 읽으면 돼요:

- `GET https://api.marketpilot.it/v1/public/ai-catalog` — JSON: 서비스 페이지(요약·적합 고객·기대 효과·태그) + 전체 상품(기본 단가·최소주문·AI 주문 가능 여부)
- `GET https://api.marketpilot.it/v1/public/ai-catalog.md` — 같은 내용의 마크다운 (LLM이 읽기 좋은 형태)
- `https://www.marketpilot.it/llms.txt` — 사이트 전체 AI 안내 진입점

추천 흐름: 공개 카탈로그로 서비스를 고르고 → 견적·주문이 필요해지면 API 키를 발급받아 아래 주문 플로우로 진행하세요.

## 인증

모든 요청에 API 키가 필요해요. 키는 마켓파일럿에 로그인한 뒤
**https://www.marketpilot.it/developer/api-keys** 에서 발급받아요 (계정당 최대 5개).

두 가지 헤더 형식을 지원해요:

```
Authorization: Bearer mk_xxxxxxxxxxxxxxxx
```
또는
```
X-API-Key: mk_xxxxxxxxxxxxxxxx
```

키는 발급한 사용자 계정에 묶여요. 주문·포인트 API는 항상 키 소유자 본인의 데이터만 다뤄요.

## 사용자(사람)를 안내해야 하는 순간

일부 단계는 AI가 대신할 수 없어요. 이때는 사용자에게 아래 URL을 안내하세요:

| 상황 | 안내할 곳 |
|---|---|
| 계정이 없음 | 회원가입 https://www.marketpilot.it/signup (이메일 또는 카카오·구글, 가입비 없음) |
| API 키가 없음 | 로그인 후 https://www.marketpilot.it/developer/api-keys 에서 발급 (최대 5개) |
| 포인트 이체 | 충전 신청 응답의 transfer 계좌로 **사용자가 직접** 계좌이체 (입금자명·금액 일치 시 몇 분 내 자동 충전) |
| 카드로 결제하고 싶음 | 웹 주문 시 토스 카드·간편결제 사용 가능 — 해당 서비스 페이지로 안내 |
| 환불·중단 요청 | 고객센터 1551-6151 · info@marketpilot.it |
| 전체 이용 방법 질문 | 이용 가이드 https://www.marketpilot.it/help |

## MCP로 연결하기 (Claude Code, Cursor 등)

MCP를 지원하는 클라이언트는 아래처럼 등록하면 도구가 자동으로 발견돼요.

Claude Code:
```bash
claude mcp add --transport http marketpilot https://api.marketpilot.it/mcp \
  --header "Authorization: Bearer mk_xxxxxxxxxxxxxxxx"
```

Cursor / VS Code (mcp.json):
```json
{
  "mcpServers": {
    "marketpilot": {
      "url": "https://api.marketpilot.it/mcp",
      "headers": { "Authorization": "Bearer mk_xxxxxxxxxxxxxxxx" }
    }
  }
}
```

MCP 도구 이름은 REST와 1:1로 대응해요: list_products, get_product, search_places,
quote_order, create_order, list_my_orders, get_my_order, get_point_balance,
request_point_charge, list_charge_requests, get_charge_request, cancel_charge_request.

## 주문 플로우 (반드시 이 순서로)

```
1. GET  /products                → 상품 목록 (aiOrderable=true인 것만 주문 가능)
2. GET  /products/{id}           → 폼 필드(formFields) 확인
3. POST /orders/quote            → 견적 (총액·잔액·quoteToken 발급, 돈 안 나감)
4. 사용자에게 상품명·수량·총액 확인   → 사람의 승인 없이 4→5로 넘어가지 마세요
5. POST /orders                  → confirm:true + quoteToken으로 주문 확정 (포인트 차감)
6. GET  /orders/{id}             → 진행 상황 확인
```

규칙:
- **견적 없이 주문 불가.** quoteToken은 15분 유효, 1회만 사용 가능해요.
- **주문 확정 전 반드시 사용자(사람)에게 확인받으세요.** 포인트가 즉시 차감돼요.
- AI 주문은 1회 최대 2,000,000원이에요. 초과분은 웹에서 주문하도록 안내하세요.
- 요청이 실패해서 재시도할 때는 먼저 `GET /orders`로 주문이 이미 생성됐는지 확인하세요.

### 예시: 견적 → 주문

```bash
# 3) 견적
curl -X POST https://api.marketpilot.it/v1/ai/orders/quote \
  -H "Authorization: Bearer mk_xxx" -H "Content-Type: application/json" \
  -d '{"productId": 12, "quantity": 100, "formData": {"nPlaceRawUrl": "https://naver.me/abc123", "targetName": "OO식당"}}'

# 응답: { "totalAmount": 50000, "pointBalance": 120000, "shortfall": 0,
#         "formValid": true, "quoteToken": "eyJ...", ... }

# 5) 확정 (사용자 확인 후)
curl -X POST https://api.marketpilot.it/v1/ai/orders \
  -H "Authorization: Bearer mk_xxx" -H "Content-Type: application/json" \
  -d '{"quoteToken": "eyJ...", "productId": 12, "quantity": 100,
       "formData": {"nPlaceRawUrl": "https://naver.me/abc123", "targetName": "OO식당"},
       "confirm": true}'
```

### 네이버 플레이스 상품의 폼 데이터

플레이스 상품은 `formData.nPlaceRawUrl`(플레이스 URL 또는 naver.me 단축 URL)만 주면
targetUrl·targetId·naverPlaceId를 서버가 자동으로 채워요.
`targetName`(업체명)은 필수예요 — `GET /search-places?keyword=업체명` 결과의 name을 쓰거나 사용자에게 물어보세요.

## 포인트: 잔액·충전

결제는 포인트로 이뤄져요 (1P = 1원). 잔액이 부족하면 충전 신청 후 주문하세요.

```
1. GET  /point/balance                       → 잔액 확인
2. POST /point/charge-requests               → 충전 신청 { amount, depositorName }
   → 응답의 transfer에 무통장 입금 계좌·금액·입금자명이 담겨요. 사용자에게 그대로 안내하세요.
3. (사용자가 직접 계좌 이체)                    → AI가 대신 이체할 수 없어요
4. GET  /point/charge-requests/{id}          → status가 CONFIRMED(충전 완료)면 주문 진행
```

- 입금자명과 금액이 신청 내용과 정확히 일치하면 **보통 몇 분 안에 자동 충전**돼요.
- `depositorName`은 사용자가 실제 이체할 때 쓸 이름과 똑같아야 해요 — 반드시 사용자에게 물어보세요.
- 충전 상태: PENDING(입금 대기) → CONFIRMED(충전 완료) / CANCELED(취소됨)
- 세금계산서·현금영수증이 필요하면 신청 시 cashReceiptType 등 증빙 필드를 함께 보내세요.

## 엔드포인트 요약

| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | /v1/public/ai-catalog | (인증 불필요) 서비스+상품 전체 카탈로그 JSON |
| GET | /v1/public/ai-catalog.md | (인증 불필요) 카탈로그 마크다운 |
| GET | /products | 주문 가능 상품 목록 (사용자별 단가 반영) |
| GET | /products/{id} | 상품 상세 + 폼 필드 명세 |
| GET | /search-places?keyword= | 네이버 플레이스 검색 (placeId·업체명) |
| POST | /orders/quote | 주문 견적 (quoteToken 발급) |
| POST | /orders | 주문 확정 (quoteToken + confirm:true) |
| GET | /orders | 내 주문 목록 (page·limit·status) |
| GET | /orders/{id} | 주문 상세 + 진행률 + 결과 URL |
| GET | /point/balance | 포인트 잔액 |
| POST | /point/charge-requests | 충전 신청 (계좌 안내 반환) |
| GET | /point/charge-requests | 충전 신청 목록 |
| GET | /point/charge-requests/{id} | 충전 신청 상태 확인 |
| POST | /point/charge-requests/{id}/cancel | 입금 대기 신청 취소 |

이 외에 마케팅 분석 도구(GET /search-places, /place/{placeId}, /keyword-volumes,
/keyword-competition, /recommended-keywords/{placeId}, POST /recommendations, /chat)도
같은 키로 사용할 수 있어요.

## 에러 형식

```json
{ "error": "포인트가 30,000P 부족해요. ...", "details": { "shortfall": 30000 } }
```

| 코드 | 의미 | 대응 |
|---|---|---|
| 401 | 키 없음/무효 | 키 확인 또는 재발급 안내 |
| 402 | 포인트 부족 | 충전 플로우로 이동 |
| 403 | 권한 없음 (고객 키 아님 등) | 고객 계정 키로 발급 안내 |
| 404 | 대상 없음 | ID 확인 |
| 409 | 견적 만료·가격 변경·중복 사용 | 견적부터 다시 |

## 주문 상태 값

paid(결제 완료) → in_progress(진행중) → completed(완료). 그 외 refunded(환불), stopped(중단).
응답의 statusLabel·phaseLabel에 한글 라벨이 함께 내려가요 — 사용자에게는 한글 라벨을 보여주세요.
