# 엔비랜드(NvLand) — AI 에이전트 연동 가이드

contract-version: 2026-07-19.v3
(모든 API 응답의 `nvland-contract-version` 헤더와 대조하세요. 불일치하면 이 문서를 다시 읽으세요.)

이 문서는 AI 코딩 에이전트(Claude Code, Codex 등)가 사용자를 대신해 엔비랜드를 쓰는 방법입니다.
**에이전트의 대리 배포를 공식 환영합니다** — 담당자 이메일만 정확하면 됩니다.

NvLand는 AI가 만든 랜딩페이지 **프로젝트(멀티파일)**를 배포하고, 리드 수집·유입 분석까지 제공합니다.
이 문서 하나로 배포 API 전체를 쓸 수 있습니다. 기계용 스키마: `GET https://nvland.docenty.ai/api/openapi.json`

## 1. 연결과 workspace 확인

기본 연결은 브라우저 OAuth 또는 일회용 페어링입니다. **장기 API 키·토큰·비밀값을 AI 대화, 복사 프롬프트, 저장소에 붙여넣지 마세요.** CI처럼 사람이 없는 환경에서만 비밀 저장소의 `NVLAND_API_KEY` 환경변수를 사용합니다.

- 사용자에게 안내: https://nvland.docenty.ai/signup 가입 → https://nvland.docenty.ai/dashboard/settings에서 브라우저 연결 또는 제한된 키 발급
- 재발급/회수: https://nvland.docenty.ai/dashboard/settings
- 인증 헤더: `Authorization: Bearer nv_live_...`
- 연결 직후: `GET https://nvland.docenty.ai/api/v1/workspaces`로 workspace 목록을 조회하고, `GET https://nvland.docenty.ai/api/v1/context`로 선택 결과를 확인합니다.
- 여러 workspace에 접근할 수 있으면 모든 요청에 `X-Nvland-Workspace: <workspace-slug>`를 넣어야 합니다. 빈 선택은 전체 workspace를 뜻하지 않습니다.

## 2. E2E 예시 — draft/noindex preview부터 시작

```bash
# 1) 배포 (JSON tier — 텍스트 파일이면 이걸로 충분)
curl -s -X POST https://nvland.docenty.ai/api/v1/deploy \
  -H "Authorization: Bearer $NVLAND_API_KEY" \
  -H "X-Nvland-Workspace: <workspace-slug>" \
  -H "Content-Type: application/json" \
  -d '{"title":"신제품 사전예약",
       "files":[{"path":"index.html","content":"<!doctype html><html><head><title>예약</title></head><body><form method=\"post\" action=\"{NVLAND_FORM_ENDPOINT}\"><input name=\"name\"><input name=\"contact\"><button>신청</button></form></body></html>"}],
       "releaseMode":"staged"}'
# 처음에는 releaseMode: "staged"로 draft/noindex preview를 만들고 URL·workspace·프로젝트를 확인한다.
# public live 전환은 별도 승인 요청으로만 수행한다.

# 2) 검증 — verify.url이 200이면 성공
curl -sI "$liveUrl" | head -1
```

바이너리 파일은 `{"path":"logo.png","contentBase64":"..."}`. 본문이 4MB를 넘으면 413과 함께
2단계 업로드 안내가 응답에 옵니다:

```bash
# zip 업로드 (큰 프로젝트): POST /api/v1/uploads → 응답의 uploadUrl에 PUT → blobUrl로 deploy
curl -s -X POST https://nvland.docenty.ai/api/v1/uploads -H "Authorization: Bearer $NVLAND_API_KEY"
curl -s -X PUT "<uploadUrl>" -H "Authorization: Bearer $NVLAND_API_KEY" --data-binary @site.zip
curl -s -X POST https://nvland.docenty.ai/api/v1/deploy -H "Authorization: Bearer $NVLAND_API_KEY" \
  -H "Content-Type: application/json" -d '{"title":"...","blobUrl":"<blobUrl>"}'
```

기존 프로젝트 업데이트: `{"projectSlug":"<slug>", "files":[...]}` — 같은 slug 재배포 = 새 버전.

### 계측·스크립트 주입 (`inject` — HTML을 손대지 않고 GA4·픽셀·챗봇 삽입)

배포 본문에 `inject`를 넣으면 배포 시점에 모든 .html의 `<head>`/`</body>`에 자동 주입됩니다
(web builder의 "커스텀 코드"와 동일). 같은 파일이라도 `inject`가 다르면 새 버전으로 배포됩니다.

```bash
curl -s -X POST https://nvland.docenty.ai/api/v1/deploy -H "Authorization: Bearer $NVLAND_API_KEY" \
  -H "Content-Type: application/json" -d '{
    "title":"창업 설명회", "files":[{"path":"index.html","content":"<!doctype html>..."}],
    "inject":{ "ga4Id":"G-XXXXXXXXXX",
               "headHtml":"<script>메타/네이버/카카오 픽셀…</script>",
               "bodyEndHtml":"<script>챗봇 embed…</script>" }
  }'
```

- `ga4Id`: `G-`로 시작하는 GA4 측정 ID만 허용 — gtag 스니펫이 `<head>`에 자동 생성됩니다.
- **프리셋 9종** (형식 검증 후 서버가 스니펫 생성 — 자유 코드 아님): `ga4Id`, `googleAdsId`(AW-…), `metaPixelId`, `kakaoPixelId`, `clarityId`, `channelIoKey`, `kakaoChannelId`(_…), `naverSiteVerification`, `naverWcsId`. 프로젝트 상세 > 마케팅 연동에 저장해두면 재배포마다 자동 적용되고, 요청의 `inject`가 저장값보다 우선합니다.
- `headHtml` / `bodyEndHtml`: 임의 코드(각 20KB 이하). 배포 페이지는 격리 샌드박스에서 서빙되어 대시보드와 분리됩니다.
- **자체 분석 자동 내장**: 모든 배포 HTML에 방문(서버측)·클릭·리드 계측이 기본 포함됩니다. 구매 버튼에 `data-nv-buy`, CMS 상품 귀속은 `data-nv-entry="<entryId>"` 속성을 쓰세요.
- **동시 배포 안전(CAS)**: 본문에 `expectedLiveDeploymentId`를 넣으면 "그 버전이 라이브일 때만" 승격됩니다. 불일치 시 409 `live_conflict` — 최신 버전 확인 후 재시도하세요 (에이전트 자동 재배포 시 권장).

### URL 가져오기 (`/api/v1/import` — 이미 배포된 페이지를 긁어서 배포)

```bash
# 서버가 URL을 fetch → 배포 (SSRF 방어: 사설/로컬 주소 거부, JS 렌더 페이지는 초기 HTML만)
curl -s -X POST https://nvland.docenty.ai/api/v1/import -H "Authorization: Bearer $NVLAND_API_KEY" \
  -H "Content-Type: application/json" -d '{"url":"https://example.com/landing"}'

# 북마클릿/에이전트가 렌더된 DOM을 직접 넘길 수도 있음 (JS 페이지 대응)
curl -s -X POST https://nvland.docenty.ai/api/v1/import -H "Authorization: Bearer $NVLAND_API_KEY" \
  -H "Content-Type: application/json" -d '{"html":"<!doctype html>...","title":"가져온 페이지"}'
```

응답은 `/api/v1/deploy`와 동일. `inject`도 함께 쓸 수 있습니다.

### 사이트 마이그레이션 (`/api/v1/migrate` — 기존 웹사이트 여러 페이지를 한 프로젝트로)

```bash
curl -s -X POST https://nvland.docenty.ai/api/v1/migrate -H "Authorization: Bearer $NVLAND_API_KEY" \
  -H "Content-Type: application/json" -d '{"url":"https://example.com"}'
```

같은 도메인 하위 페이지를 최대 20개(깊이 2)까지 크롤 → 멀티파일로 배포. 내부 링크는 사이트 내 상대경로로, 자산은 원본 오리진에서 로드. 응답에 `migrated.pages`(마이그레이션 수)·`migrated.paths`. JS 렌더 페이지는 초기 HTML만 잡힙니다.

### CLI (`npx nvland` — 브라우저 승인 후 단일 HTML 배포)

에이전트/개발자가 API 키를 복사하지 않고 사용할 수 있는 경로입니다. `login`은 브라우저 세션 승인과 PKCE를 사용하며, 토큰은 사용자 전용 권한의 로컬 설정 파일에 저장됩니다.

```bash
npx nvland login
npx nvland whoami
npx nvland deploy index.html
npx nvland pages
npx nvland leads
npx nvland logout
```

현재 CLI `deploy`는 지정한 단일 HTML 파일을 `index.html`로 배포합니다. 멀티파일/zip 배포, 재배포 slug 지정, API 키 기반 자동화는 위 REST API 또는 MCP를 사용하세요. self-hosted API는 `NVLAND_API_URL=https://…`로 지정합니다.

## 3. 제한 (초과 시 구조화 에러)

- 파일 200개 · 총 30MB · 단일 파일 10MB · JSON 본문 4MB
- 배포 rate limit: 분당 10회 (429 + Retry-After)
- 버전 보존: 프로젝트당 3세대 (초과분은 아카이브 — 롤백 불가)
- 지원 확장자: html, css, js, mjs, json, txt, xml, png, jpg, jpeg, gif, webp, svg, ico, avif, woff, woff2, ttf, otf, webmanifest, pdf, mp4, webm
- zip 규칙: 루트(또는 단일 최상위 폴더)에 index.html 필수, 심볼릭 링크·경로 탈출 거부

## 4. 페이지 규약 (플레이스홀더)

- 리드폼: `<form method="post" action="{NVLAND_FORM_ENDPOINT}">` — 배포 시 자동 연결.
  필드명: `name`(필수), `contact`(필수), `message`(선택), 스팸 방지 `<input name="hp" style="display:none">` 권장.
- index.html은 `<head>`·`<body>` 포함 완성 HTML이어야 합니다.
- 응답의 `warnings`가 비어있지 않으면 **반드시 사용자에게 보고**하세요 (예: lead_form_missing).

## 5. 에러 코드 (전 API 공통 `{"error":{"code","message","hint","doc"}}`)

| code | 의미 | 조치 |
|---|---|---|
| unauthorized | 키 없음/잘못됨/회수됨 | 사용자에게 키 재발급 요청 |
| payload_too_large | JSON 4MB 초과 | 2단계 업로드(위 §2) |
| zip_invalid / zip_bomb / path_traversal | zip 문제 | hint대로 재압축 |
| index_missing | index.html 없음 | 루트에 index.html 배치 |
| file_too_large / too_many_files / unsupported_file_type | 캡·형식 | hint 참조 |
| rate_limited | 분당 초과 | Retry-After 초 후 재시도 |
| plan_limit (402) | 요금제 페이지 한도 도달 | 기존 프로젝트 업데이트(projectSlug 지정) 또는 요금제 업그레이드 |
| import_failed | URL 가져오기/마이그레이션 실패 (형식·SSRF 차단·크기 등) | hint대로 URL·HTML 수정 후 재시도 |
| blob_failure / internal | 서버 측 | 재시도 (라이브는 불변) — Idempotency-Key 사용 권장 |

재시도 규약: `Idempotency-Key: <uuid>` 헤더를 보내면 타임아웃 후 재시도해도 중복 배포가 생기지 않습니다.
같은 파일 내용 재배포도 자동으로 기존 배포를 반환합니다(reused: true).

## 6. 조회·롤백

```bash
curl -s https://nvland.docenty.ai/api/v1/projects -H "Authorization: Bearer $NVLAND_API_KEY"          # 목록
curl -s https://nvland.docenty.ai/api/v1/projects/<slug> -H "Authorization: Bearer $NVLAND_API_KEY"    # 상태·버전
curl -s -X POST https://nvland.docenty.ai/api/v1/projects/<slug>/rollback -H "Authorization: Bearer $NVLAND_API_KEY"  # 직전 버전으로
```

API가 안 되면 대시보드 붙여넣기(https://nvland.docenty.ai/dashboard/new)가 항상 동작합니다 (사람 fallback).

### AI 마케팅 리포트 (`/api/reports` — 세션 인증, 대시보드용)

방문·클릭·리드 데이터로 주간 진단과 페이지 수정안을 생성합니다. 무료 플랜은 수동 주 1회, 유료는 자동 주간 리포트(cron). 데이터가 적으면(주 30방문 미만) 진단 대신 체크리스트를 반환합니다.

## 7. 확인할 것

- 방문·유입: https://nvland.docenty.ai/dashboard/marketing (utm_source 별 분해)
- 리드: 폼 제출 → 저장·중복 병합 → 대시보드 표시
- 요금: Free $0 (페이지 1개) · Marketing Basic $5/월 (페이지 10개) · Marketing CRM $20/월 (페이지 100개)

## 8. 기타 연동 수단

### MCP (Claude Code·Codex — 한 줄 연결, 지금 사용 가능)

```bash
claude mcp add --transport http nvland https://nvland.docenty.ai/api/mcp \
  --header "Authorization: Bearer $NVLAND_API_KEY"
```

연결되면 대화에서 바로 쓰는 도구: `deploy_page`(배포→라이브 URL) · `list_pages`(방문·리드 수) · `get_leads`(최근 리드) · `list_agent_capabilities`(랜딩·콘텐츠·커머스 Store 작업 탐색)입니다.

### Store-aware Agent 작업 (Claude/Codex · Hermes · Commerce-Nax-OS)

먼저 `list_agent_capabilities`를 호출해 작업 경계와 연결된 Store를 확인하세요. 현재 공개된 조합은 다음과 같습니다.

- `landing-candidates`: Target/Pack → 정확히 A/B/C noindex preview 후보. branch/PR은 고객 저장소의 로컬 bridge만 사용합니다.
- `product-knowledge` → `content-drafts`: 출처가 연결된 상품 지식 → blog/product_page/reels 초안. `generate_content_draft`는 게시하지 않습니다.
- `commerce-catalog`: local 상품 mirror 읽기. 원격 상품 변경 및 주문 수취인 정보는 제외됩니다.
- `approved-external-write`: 게시·production release·fulfillment은 `request_external_write`로 승인 요청만 만들 수 있습니다.

Hermes agent나 Commerce-Nax-OS는 별도 webhook·credential 전달 없이 같은 MCP 또는 아래 REST 계약을 pull 방식으로 읽어 연결할 수 있습니다. `POST /api/v1/agent/handoffs`는 비밀 없는 연결 envelope만 반환하며 외부 시스템을 호출하지 않습니다.

```bash
curl -H "Authorization: Bearer $NVLAND_API_KEY" https://nvland.docenty.ai/api/v1/agent/capabilities
curl -X POST https://nvland.docenty.ai/api/v1/agent/handoffs \
  -H "Authorization: Bearer $NVLAND_API_KEY" -H "Content-Type: application/json" \
  -d '{"consumer":"hermes","capabilityId":"content-drafts","referenceIds":["knowledge:42"]}'
```

### Repository-native Landing Target (Agentify 선택)

NvLand만으로 바로 시작하려면 고객 저장소에서 Target Packet을 만드세요. 기본 Next/Vite 명령만 자동 감지하며, 그 밖의 frontend는 안전한 build/preview 명령을 명시해야 합니다.

```bash
nvland launch target init ./customer-repo --mode customer_ci
nvland launch prompt ./customer-repo/.nvland/launch-target.json --pack nvland-hospital-geo-landing --candidate a
```

Agentify의 `launch-target scan/setup/verify`는 필수가 아닙니다. monorepo의 frontend 경계·API discovery·재현성 검토를 더 엄격히 해야 할 때 같은 Packet 형식으로 보완할 수 있습니다.

### 마케팅 연동 프리셋 (Claude·Codex·Hermes 공통 — 읽고 채우기)

```bash
curl -s https://nvland.docenty.ai/api/v1/projects/<slug>/connectors -H "Authorization: Bearer $NVLAND_API_KEY"     # 현재 설정
curl -s -X PUT https://nvland.docenty.ai/api/v1/projects/<slug>/connectors -H "Authorization: Bearer $NVLAND_API_KEY" \
  -H "Content-Type: application/json" -d '{"ga4Id":"G-XXXXXXXXXX","metaPixelId":"123456789012345"}'
```

병합 저장: 보낸 키만 갱신, `""`은 해제. 형식 미달 값은 `dropped`로 반환. 사용자의 기존 사이트 HTML에서
gtag(G-)·AW-·fbq init·kakaoPixel·clarity 태그를 찾아 채우는 패턴을 권장한다. 저장 후 재배포 시 자동 주입.

### 리소스 API (ID 기반 조회 — 대시보드 "AI에서 활용" 버튼과 같은 체계)

```bash
curl -s https://nvland.docenty.ai/api/v1/resources -H "Authorization: Bearer $NVLAND_API_KEY"                     # 카탈로그
curl -s https://nvland.docenty.ai/api/v1/resources/marketing.funnel -H "Authorization: Bearer $NVLAND_API_KEY"    # 7일 퍼널·전주 비교·유입 채널
curl -s https://nvland.docenty.ai/api/v1/resources/leads.recent -H "Authorization: Bearer $NVLAND_API_KEY"        # 최근 리드 50
```

응답의 `related[]` 링크로 인접 데이터를 이어서 조회하라 (퍼널 ↔ 리드 ↔ 페이지).

### CLI OAuth

`npx nvland login`은 브라우저에서 NvLand 계정 승인을 연 뒤 PKCE로 안전하게 토큰을 받습니다. API 키를 복사하지 않아도 `npx nvland deploy index.html`, `npx nvland pages`, `npx nvland leads`를 실행할 수 있습니다. Google Analytics·Ads 연결, 권한 부족, quota 오류는 대시보드 설정에서 확인·재연결합니다.

### 단일 페이지 레거시 API — `/api/v1/pages` (90일 호환 유지)

멀티파일 `/api/v1/deploy` 도입 전의 단일 HTML 배포 API입니다. 기존 연동을 위해 **90일간 호환을 유지**합니다.
신규 연동은 `/api/v1/deploy`를 쓰세요.

```bash
curl -X POST https://nvland.docenty.ai/api/v1/pages \
  -H "Authorization: Bearer $NVLAND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"신제품 사전예약","html":"<!doctype html>..."}'
# → 201 {"ok":true,"slug":"...","url":"https://nvland.docenty.ai/p/...","leadEndpoint":"/api/leads/12"}

# 내 페이지 목록
curl -H "Authorization: Bearer $NVLAND_API_KEY" https://nvland.docenty.ai/api/v1/pages
```

---
문의: contact+nvland@docenty.ai · 이 문서: https://nvland.docenty.ai/agents.md · 스키마: https://nvland.docenty.ai/api/openapi.json
