API 키 발급 — 1분
키는 에이전트가 내 계정으로 발행하기 위한 열쇠입니다. 이 자리에서 바로 발급됩니다 — 발급하면 아래 2단계의 명령어에 키가 자동으로 채워집니다.
- · 키는 발급 직후 한 번만 표시됩니다 — 아래 명령어를 이 화면에서 바로 복사하세요.
- · 발급한 키의 목록·폐기는 설정 → API 키에서.
쓰는 에이전트에 연결
아래에서 쓰는 도구 하나만 골라 따라 하세요. 명령어의 op_내_키 자리에 1단계에서 발급한 키를 넣습니다.
Claude Code
지금 바로터미널에서 아래 한 줄이면 끝. 이후 Claude Code가 onepage_publish 같은 도구를 알아서 씁니다.
claude mcp add --transport http onepage https://1page.run/api/mcp --header "Authorization: Bearer op_내_키"
Cursor
지금 바로~/.cursor/mcp.json(전역) 또는 프로젝트의 .cursor/mcp.json에 아래를 추가하세요.
{
"mcpServers": {
"onepage": {
"url": "https://1page.run/api/mcp",
"headers": { "Authorization": "Bearer op_내_키" }
}
}
}그 외 코딩 에이전트 (Codex CLI, Devin 등)
지금 바로MCP가 없어도 됩니다. 이 페이지 맨 아래의 에이전트 가이드 원문을 CLAUDE.md·AGENTS.md 등 에이전트 지침 파일에 붙여넣고, 키는 환경변수 ONEPAGE_API_KEY로 두면 에이전트가 REST API를 직접 호출합니다.
claude.ai 웹 · Claude Desktop
준비 중claude.ai의 커스텀 커넥터는 OAuth 로그인을 요구합니다. 1page.run의 OAuth 지원을 준비 중이며, 열리면 URL 하나 등록으로 연결됩니다. 그때까지는 Claude가 만든 HTML을 홈 드랍존에 붙여넣는 게 가장 빠릅니다.
ChatGPT
준비 중ChatGPT 커넥터도 마찬가지로 OAuth 지원 후 열립니다. 지금은 ChatGPT가 만든 결과물을 홈 드랍존에 붙여넣어 발행하세요 — 로그인 없이도 됩니다.
이렇게 말해보세요
연결이 끝났다면 별도 명령어는 없습니다. 그냥 대화하세요.
"방금 만든 랜딩페이지, 1page.run에 발행해줘"
→ 30초 뒤 공유 링크가 돌아옵니다
"헤더를 검정으로 바꾸고 같은 링크로 업데이트해줘"
→ URL은 그대로, 내용만 바뀝니다. 받은 사람은 새로고침만 하면 됩니다
"내가 발행한 페이지 목록 보여줘"
→ 제목·링크·조회수를 정리해서 보여줍니다
"이번 주 보고서 3개를 weekly 컬렉션으로 묶어서 올려줘"
→ 자동 목차가 있는 컬렉션 페이지가 생깁니다
핵심은 두 번째입니다 — 한 번 공유한 링크는 죽지 않습니다. 피드백을 받고 에이전트에게 고치라고 하면, 같은 URL이 새 내용을 보여줍니다.
앞으로 열리는 것
- OAuth 로그인 연결 — claude.ai·ChatGPT 커넥터에서 키 복사 없이 “1page.run으로 로그인” 한 번으로 연결
- 원클릭 설치 — “Add to Cursor” 버튼처럼 명령어 복사 없이 버튼 하나로 연결
- MCP 레지스트리 등재 — 클라이언트의 서버 디렉토리에서 1page.run을 바로 검색·설치
에이전트 가이드 원문
CLAUDE.md 등에 붙여넣는 전문 — 에이전트가 직접 읽게 하려면 https://1page.run/llms.txt를 fetch하라고 해도 됩니다
# 1page.run API — 에이전트 가이드
HTML 또는 Markdown을 게시하면 즉시 공유 가능한 영구 URL이 됩니다.
이 문서 전체를 에이전트 지침(CLAUDE.md, 시스템 프롬프트 등)에 붙여넣어 쓰세요.
원문: https://1page.run/llms.txt
- Base URL: `https://1page.run/api/v1`
- 인증: 모든 요청에 `Authorization: Bearer <API_KEY>` 헤더. 키는 https://1page.run/settings 에서 발급 (`op_`로 시작)
- 키 보관 컨벤션: 환경변수 `ONEPAGE_API_KEY`에 두는 것을 권장합니다. MCP로 연결한 경우에도 REST를 병용한다면 같은 키를 이 환경변수로 노출해 두세요.
- 본문은 JSON. 실패 시 `{ "error": { "code": "...", "message": "..." } }` + HTTP 상태코드
- 제한: 콘텐츠 2MB, 키당 분당 쓰기 10회 · 읽기 60회 (429면 잠시 후 재시도)
## 페이지 게시
`POST /pages`
```json
{
"title": "주간 리포트",
"html": "<!doctype html>... 또는 Markdown 원문",
"contentType": "html",
"collection": "my-collection",
"description": "이번 주 완료 항목과 다음 주 계획 요약.",
"note": "Claude 대화에서 생성 — 주간 보고 자동화. 프롬프트: '지난주 커밋 요약해서…'",
"ogImage": "https://example.com/cover.png"
}
```
- `contentType`: `"html"`(기본) 또는 `"markdown"`. Markdown일 때도 원문은 `html` 필드에 넣습니다.
- `collection`: 선택. 내 컬렉션의 slug — 게시와 동시에 그 컬렉션 맨 뒤에 배치됩니다.
- `title` 생략 시 콘텐츠에서 자동 유도됩니다 (Markdown: frontmatter `title` > 첫 헤딩, HTML: `<title>`).
- **공유 미리보기(OG) — 링크를 카톡/슬랙/X에 붙였을 때 뜨는 제목·설명·썸네일:**
- `title` → og:title, `description` → og:description(~2문장 권장, 최대 300자), `ogImage` → og:image.
- `ogImage`는 **공개 접근되는 외부 이미지 URL을 그대로** 넣으면 됩니다(http(s)://, 권장 1200×630). 1page.run에 업로드할 필요 없습니다.
- 생략하면 `description`은 본문 앞부분에서 자동 추출, 썸네일은 제목 기반 이미지가 자동 생성됩니다. slug가 랜덤이라도 미리보기는 이렇게 채워집니다.
- Markdown이면 위 세 값을 요청 필드 대신 문서 맨 앞 `---` frontmatter(`title`, `description`, `image`; 그밖에 `author`, `date`, `tags`)로 넣어도 동일하게 적용됩니다. 요청 필드와 frontmatter가 겹치면 요청 필드가 우선입니다. `date: false`로 날짜 표시를 끌 수 있습니다.
- 응답: `201 { "page": { "slug", "url", "title", "collection", "createdAt" } }` — 이 `url`을 사용자에게 전달하세요.
- **중복 게시 감지**: 지정한 컬렉션에 같은 `title`의 페이지가 이미 있으면 응답에 `existingPage`(`slug`, `url`, `updatedAt`)와 `warning`이 함께 옵니다. 같은 문서를 갱신하려던 것이었다면 방금 만든 페이지를 `DELETE`하고 `existingPage.slug`에 `PATCH` 하세요.
## 페이지 읽기 — 본문 포함 단건 조회
`GET /pages/{slug}` → `{ "page": { "slug", "url", "title", "html", "contentType", "collection", "position", "visibility", "description", "note", "ogImage", "views", "createdAt", "updatedAt" } }`
- `html`에 저장된 원문(HTML 또는 Markdown)이 그대로 담깁니다. 기존 페이지를 부분 수정할 때는 **이 엔드포인트로 현재 본문을 받아 고친 뒤 PATCH** 하세요 — 로컬에 원본이 없어도 제자리 갱신이 가능합니다.
- **`?include_html=false`** — 본문 대신 구조화 요약 `summary: { bytes, headings[], excerpt }`가 옵니다. 소속·메타·"무슨 문서인지"만 확인할 때 큰 본문을 받지 마세요.
- 내 소유 페이지만 조회됩니다. 미존재·비소유 모두 `404 PAGE_NOT_FOUND`.
## 페이지 수정 — 같은 URL 제자리 갱신
`PATCH /pages/{slug}` — 보낸 필드만 갱신됩니다.
- 필드: `title`, `html`, `contentType`, `collection`(slug 또는 `null`=컬렉션에서 분리), `position`(0 이상 정수), `description`, `ogImage`
- `description`·`ogImage`에 빈 문자열(`""`) 또는 `null`을 보내면 명시값을 지워 자동 추출/생성으로 되돌립니다.
- 같은 문서를 다시 게시할 때는 새 페이지를 만들지 말고 반드시 PATCH로 갱신하세요. URL은 변하지 않습니다. slug를 잊었다면 `GET /pages`에서 title로 찾으세요.
## 페이지 목록 · 삭제
- `GET /pages?collection={slug}&q={제목검색}&sort=recent|views&limit=50&offset=0` → `{ "total", "pages": [ { "slug", "url", "title", "collection", "position", "contentType", "visibility", "views", "createdAt", "updatedAt" } ] }` (본문 미포함 — 본문은 `GET /pages/{slug}`)
- `q`: 제목 부분 일치(대소문자 무시) — "그 페이지 slug가 뭐였지"는 이걸로 찾으세요. `sort`: `recent`(기본, 최신 발행순) / `views`(누적 조회순). `total`은 필터 기준 전체 개수 — offset을 늘려 다음 페이지를 받으세요.
- `DELETE /pages/{slug}` → `{ "success": true }` (soft delete — 이후 해당 링크는 404. 삭제 확인은 링크 상태코드로 가능)
## 컬렉션 — 페이지를 묶는 자동 목차
- `POST /collections` — `{ "title": "...", "slug"?: "...", "description"?: "..." }` (slug는 소문자/숫자/하이픈 3~32자, 생략 시 자동 생성) → `201 { "collection": { "slug", "url", "title", "createdAt" } }`
- `GET /collections` → `{ "collections": [ { "slug", "url", "title", "description", "pageCount", "createdAt" } ] }`
- `PATCH /collections/{slug}` — 보낸 필드만 갱신: `title`, `description`(`""`/`null`=제거), `unlisted`(true=링크로만 공개, false=프로필·목록 노출), `showAuthor`(작성자 표시). slug(URL)는 불변입니다.
- 컬렉션 **삭제**와 페이지 **순서 변경** API는 의도적으로 제공하지 않습니다 — 웹(https://1page.run/dashboard)에서만 가능합니다. 페이지의 소속 변경은 `PATCH /pages/{slug}`의 `collection` 필드로 하세요.
## 인사이트 — 조회 통계 (계정 전체 / 페이지 한 장 / 컬렉션)
`GET /insights?days=30` (days 1~90, 기본 30) → `{ "insights": { "days", "totalPages", "totals": { "views", "visitors" }, "topPages": [ { "slug", "url", "title", "views" } ], "referrers", "countries", "devices", "daily", "profile" } }`
- "인기 페이지가 뭔지 · 조회/순방문이 얼마나 되는지 · 어디서 유입되는지"를 한 번에 답할 때 사용하세요.
- **`&slug={slug}`** — 그 페이지 한 장으로 축소. "어제 보낸 페이지 누가 봤어?"는 이걸로 답하세요 (응답에 `lifetimeViews`=누적 조회 포함, `topPages`/`profile` 없음).
- **`&collection={slug}`** — 그 컬렉션 소속 페이지 합산 (slug와 동시 지정 불가).
- `totalPages`는 살아있는 페이지 총수(기간 무관). 집계는 쿠키 없는 비콘 기준, 봇 필터 적용. 소유자 본인 방문은 제외됩니다.
## 에러 코드
모든 실패 응답은 `{ "error": { "code", "message" } }` 형태입니다.
| HTTP | code | 의미 |
|---|---|---|
| 400 | `INVALID_JSON` · `HTML_REQUIRED` · `TITLE_REQUIRED` · `EMPTY_PATCH` | 본문 누락/형식 오류 |
| 400 | `INVALID_TITLE` · `INVALID_DESCRIPTION` · `INVALID_OG_IMAGE` · `INVALID_COLLECTION` · `INVALID_POSITION` · `INVALID_VISIBILITY` · `INVALID_UNLISTED` · `INVALID_SHOW_AUTHOR` · `INVALID_DAYS` · `INVALID_SORT` · `INVALID_SCOPE` · `UNSUPPORTED_CONTENT_TYPE` · `SLUG_INVALID` | 필드 값 오류 |
| 401 | `UNAUTHORIZED` | API 키 누락/무효 |
| 404 | `PAGE_NOT_FOUND` · `COLLECTION_NOT_FOUND` | 미존재 또는 비소유 (존재 여부는 비노출) |
| 409 | `SLUG_TAKEN` | 컬렉션 slug 중복 (페이지 slug는 서버가 발급하므로 중복 없음) |
| 413 | `HTML_TOO_LARGE` | 콘텐츠 2MB 초과 |
| 429 | `RATE_LIMITED` | 레이트 리밋 — 잠시 후 재시도 |
## 예시 (curl)
```bash
curl -X POST https://1page.run/api/v1/pages \
-H "Authorization: Bearer $ONEPAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"주간 리포트","contentType":"markdown","html":"# 주간 리포트\n\n이번 주 완료 항목입니다."}'
```
## 규칙
- 한 번 만들어진 URL은 죽지 않습니다. 링크를 바꾸지 말고 PATCH로 내용을 갱신하세요.
- 기존 페이지를 고칠 때는 `GET /pages/{slug}`로 현재 본문을 읽고 시작하세요 — 로컬 사본이 없어도 됩니다.
- 게시물은 기본적으로 unlisted — 링크를 아는 사람만 볼 수 있고 목록/검색에는 노출되지 않습니다.
- 작업을 마치면 결과 `url`을 사용자에게 보여주세요.