REST API 참조
EmDash는 콘텐츠 관리, 미디어 업로드 및 스키마 작업을 위한 REST API를 /_emdash/api/에서 제공합니다.
API 요청에는 Bearer 토큰을 통한 인증이 필요합니다:
Authorization: Bearer <token>토큰은 관리자 인터페이스 또는 프로그래밍 방식으로 생성할 수 있습니다.
응답 형식
섹션 제목: “응답 형식”모든 응답은 일관된 형식을 따릅니다:
// Success{ "success": true, "data": { ... }}
// 오류{ "success": false, "error": { "code": "ERROR_CODE", "message": "사람이 읽을 수 있는 메시지", "details": { ... } }}콘텐츠 엔드포인트
섹션 제목: “콘텐츠 엔드포인트”콘텐츠 목록 조회
섹션 제목: “콘텐츠 목록 조회”GET /_emdash/api/content/:collection매개변수
섹션 제목: “매개변수”| 매개변수 | 유형 | 설명 |
|---|---|---|
collection | string | 컬렉션 슬러그 (경로) |
cursor | string | 페이지네이션 커서 (쿼리) |
limit | number | 페이지당 항목 수 (쿼리, 기본값: 50) |
status | string | 상태별 필터 (쿼리) |
orderBy | string | 정렬 기준 필드 (쿼리) |
order | string | 정렬 방향: asc 또는 desc (쿼리) |
{ "success": true, "data": { "items": [ { "id": "01HXK5MZSN...", "type": "posts", "slug": "hello-world", "data": { "title": "안녕하세요", ... }, "status": "published", "createdAt": "2025-01-24T12:00:00Z", "updatedAt": "2025-01-24T12:00:00Z" } ], "nextCursor": "eyJpZCI6..." }}콘텐츠 조회
섹션 제목: “콘텐츠 조회”GET /_emdash/api/content/:collection/:id{ "success": true, "data": { "item": { "id": "01HXK5MZSN...", "type": "posts", "slug": "hello-world", "data": { "title": "안녕하세요", ... }, "status": "published", "createdAt": "2025-01-24T12:00:00Z", "updatedAt": "2025-01-24T12:00:00Z" } }}콘텐츠 생성
섹션 제목: “콘텐츠 생성”POST /_emdash/api/content/:collectionContent-Type: application/json요청 본문
섹션 제목: “요청 본문”{ "data": { "title": "New Post", "content": [...] }, "slug": "new-post", "status": "draft"}{ "success": true, "data": { "item": { ... } }}콘텐츠 업데이트
섹션 제목: “콘텐츠 업데이트”PUT /_emdash/api/content/:collection/:idContent-Type: application/json요청 본문
섹션 제목: “요청 본문”{ "data": { "title": "Updated Title" }, "status": "published"}콘텐츠 삭제
섹션 제목: “콘텐츠 삭제”DELETE /_emdash/api/content/:collection/:id{ "success": true, "data": { "success": true }}미디어 엔드포인트
섹션 제목: “미디어 엔드포인트”미디어 목록 조회
섹션 제목: “미디어 목록 조회”GET /_emdash/api/media매개변수
섹션 제목: “매개변수”| 매개변수 | 유형 | 설명 |
|---|---|---|
cursor | string | 페이지네이션 커서 |
limit | number | 페이지당 항목 수 (기본값: 20) |
mimeType | string | MIME 유형 접두사로 필터링 |
{ "success": true, "data": { "items": [ { "id": "01HXK5MZSN...", "filename": "photo.jpg", "mimeType": "image/jpeg", "size": 102400, "width": 1920, "height": 1080, "url": "https://cdn.example.com/photo.jpg", "createdAt": "2025-01-24T12:00:00Z" } ], "nextCursor": "eyJpZCI6..." }}미디어 조회
섹션 제목: “미디어 조회”GET /_emdash/api/media/:id미디어 생성
섹션 제목: “미디어 생성”POST /_emdash/api/mediaContent-Type: application/json요청 본문
섹션 제목: “요청 본문”{ "filename": "photo.jpg", "mimeType": "image/jpeg", "size": 102400, "width": 1920, "height": 1080, "storageKey": "uploads/photo.jpg"}미디어 업데이트
섹션 제목: “미디어 업데이트”PUT /_emdash/api/media/:idContent-Type: application/json요청 본문
섹션 제목: “요청 본문”{ "alt": "Photo description", "caption": "Photo caption"}미디어 삭제
섹션 제목: “미디어 삭제”DELETE /_emdash/api/media/:id미디어 파일 조회
섹션 제목: “미디어 파일 조회”GET /_emdash/api/media/file/:key실제 파일 내용을 제공합니다. 로컬 저장소 전용입니다.
리비전 엔드포인트
섹션 제목: “리비전 엔드포인트”리비전 목록 조회
섹션 제목: “리비전 목록 조회”GET /_emdash/api/content/:collection/:entryId/revisions매개변수
섹션 제목: “매개변수”| 매개변수 | 유형 | 설명 |
|---|---|---|
limit | number | 반환할 최대 리비전 수 (기본값: 50) |
{ "success": true, "data": { "items": [ { "id": "01HXK5MZSN...", "collection": "posts", "entryId": "01HXK5MZSN...", "data": { ... }, "createdAt": "2025-01-24T12:00:00Z" } ], "total": 5 }}리비전 조회
섹션 제목: “리비전 조회”GET /_emdash/api/revisions/:revisionId리비전 복원
섹션 제목: “리비전 복원”POST /_emdash/api/revisions/:revisionId/restore콘텐츠를 이 리비전의 상태로 복원하고 새 리비전을 생성합니다.
스키마 엔드포인트
섹션 제목: “스키마 엔드포인트”컬렉션 목록 조회
섹션 제목: “컬렉션 목록 조회”GET /_emdash/api/schema/collections{ "success": true, "data": { "items": [ { "id": "01HXK5MZSN...", "slug": "posts", "label": "Posts", "labelSingular": "Post", "supports": ["drafts", "revisions", "preview"] } ] }}컬렉션 조회
섹션 제목: “컬렉션 조회”GET /_emdash/api/schema/collections/:slug매개변수
섹션 제목: “매개변수”| 매개변수 | 유형 | 설명 |
|---|---|---|
includeFields | boolean | 필드 정의 포함 여부 (쿼리) |
컬렉션 생성
섹션 제목: “컬렉션 생성”POST /_emdash/api/schema/collectionsContent-Type: application/json요청 본문
섹션 제목: “요청 본문”{ "slug": "products", "label": "Products", "labelSingular": "Product", "description": "Product catalog", "supports": ["drafts", "revisions"]}컬렉션 업데이트
섹션 제목: “컬렉션 업데이트”PATCH /_emdash/api/schema/collections/:slugContent-Type: application/json컬렉션 삭제
섹션 제목: “컬렉션 삭제”DELETE /_emdash/api/schema/collections/:slug매개변수
섹션 제목: “매개변수”| 매개변수 | 유형 | 설명 |
|---|---|---|
force | boolean | 컬렉션에 콘텐츠가 있어도 삭제 (쿼리) |
필드 목록 조회
섹션 제목: “필드 목록 조회”GET /_emdash/api/schema/collections/:slug/fields필드 생성
섹션 제목: “필드 생성”POST /_emdash/api/schema/collections/:slug/fieldsContent-Type: application/json요청 본문
섹션 제목: “요청 본문”{ "slug": "price", "label": "Price", "type": "number", "required": true, "validation": { "min": 0 }}필드 업데이트
섹션 제목: “필드 업데이트”PATCH /_emdash/api/schema/collections/:collectionSlug/fields/:fieldSlugContent-Type: application/json필드 삭제
섹션 제목: “필드 삭제”DELETE /_emdash/api/schema/collections/:collectionSlug/fields/:fieldSlug필드 순서 재지정
섹션 제목: “필드 순서 재지정”POST /_emdash/api/schema/collections/:slug/fields/reorderContent-Type: application/json요청 본문
섹션 제목: “요청 본문”{ "fieldSlugs": ["title", "content", "author", "publishedAt"]}스키마 내보내기
섹션 제목: “스키마 내보내기”스키마 내보내기 (JSON)
섹션 제목: “스키마 내보내기 (JSON)”GET /_emdash/api/schemaAccept: application/json스키마 내보내기 (TypeScript)
섹션 제목: “스키마 내보내기 (TypeScript)”GET /_emdash/api/schema?format=typescriptAccept: text/typescript모든 컬렉션에 대한 TypeScript 인터페이스를 반환합니다.
플러그인 엔드포인트
섹션 제목: “플러그인 엔드포인트”플러그인 목록 조회
섹션 제목: “플러그인 목록 조회”GET /_emdash/api/plugins플러그인 조회
섹션 제목: “플러그인 조회”GET /_emdash/api/plugins/:pluginId플러그인 활성화
섹션 제목: “플러그인 활성화”POST /_emdash/api/plugins/:pluginId/enable플러그인 비활성화
섹션 제목: “플러그인 비활성화”POST /_emdash/api/plugins/:pluginId/disable오류 코드
섹션 제목: “오류 코드”| 코드 | HTTP 상태 | 설명 |
|---|---|---|
NOT_FOUND | 404 | 리소스를 찾을 수 없음 |
VALIDATION_ERROR | 400 | 잘못된 입력 데이터 |
UNAUTHORIZED | 401 | 토큰이 없거나 유효하지 않음 |
FORBIDDEN | 403 | 권한 부족 |
CONTENT_LIST_ERROR | 500 | 콘텐츠 목록 조회 실패 |
CONTENT_CREATE_ERROR | 500 | 콘텐츠 생성 실패 |
CONTENT_UPDATE_ERROR | 500 | 콘텐츠 업데이트 실패 |
CONTENT_DELETE_ERROR | 500 | 콘텐츠 삭제 실패 |
MEDIA_LIST_ERROR | 500 | 미디어 목록 조회 실패 |
MEDIA_CREATE_ERROR | 500 | 미디어 생성 실패 |
SCHEMA_ERROR | 400 | 스키마 작업 실패 |
DUPLICATE_SLUG | 409 | 슬러그가 이미 존재함 |
RESERVED_SLUG | 400 | 슬러그가 예약됨 |
검색 엔드포인트
섹션 제목: “검색 엔드포인트”전역 검색
섹션 제목: “전역 검색”GET /_emdash/api/search?q=hello+world매개변수
섹션 제목: “매개변수”| 매개변수 | 유형 | 설명 |
|---|---|---|
q | string | 검색어 (필수) |
collections | string | 쉼표로 구분된 컬렉션 슬러그 |
status | string | 상태별 필터 (기본값: published) |
limit | number | 최대 결과 수 (기본값: 20) |
cursor | string | 페이지네이션 커서 |
{ "results": [ { "collection": "posts", "id": "01HXK5MZSN...", "slug": "hello-world", "title": "안녕하세요", "snippet": "...this is a <mark>hello</mark> <mark>world</mark> example...", "score": 0.95 } ], "nextCursor": "eyJvZmZzZXQiOjIwfQ"}검색 제안
섹션 제목: “검색 제안”GET /_emdash/api/search/suggest?q=hel&limit=5자동 완성을 위한 접두사 일치 제목을 반환합니다.
검색 인덱스 재구축
섹션 제목: “검색 인덱스 재구축”POST /_emdash/api/search/rebuild모든 또는 특정 컬렉션에 대한 FTS 인덱스를 재구축합니다.
검색 통계
섹션 제목: “검색 통계”GET /_emdash/api/search/stats컬렉션별 인덱싱된 문서 수를 반환합니다.
섹션 엔드포인트
섹션 제목: “섹션 엔드포인트”섹션 목록 조회
섹션 제목: “섹션 목록 조회”GET /_emdash/api/sectionsGET /_emdash/api/sections?source=themeGET /_emdash/api/sections?search=newsletter섹션 조회
섹션 제목: “섹션 조회”GET /_emdash/api/sections/:slug섹션 생성
섹션 제목: “섹션 생성”POST /_emdash/api/sectionsContent-Type: application/json
{ "slug": "my-section", "title": "My Section", "keywords": ["keyword1"], "content": [...]}섹션 업데이트
섹션 제목: “섹션 업데이트”PUT /_emdash/api/sections/:slug섹션 삭제
섹션 제목: “섹션 삭제”DELETE /_emdash/api/sections/:slug설정 엔드포인트
섹션 제목: “설정 엔드포인트”모든 설정 조회
섹션 제목: “모든 설정 조회”GET /_emdash/api/settings설정 업데이트
섹션 제목: “설정 업데이트”POST /_emdash/api/settingsContent-Type: application/json
{ "siteTitle": "내 사이트", "tagline": "훌륭한 사이트", "postsPerPage": 10}메뉴 엔드포인트
섹션 제목: “메뉴 엔드포인트”메뉴 목록 조회
섹션 제목: “메뉴 목록 조회”GET /_emdash/api/menus메뉴 조회
섹션 제목: “메뉴 조회”GET /_emdash/api/menus/:name메뉴 생성
섹션 제목: “메뉴 생성”POST /_emdash/api/menusContent-Type: application/json
{ "name": "footer", "label": "Footer Navigation"}메뉴 업데이트
섹션 제목: “메뉴 업데이트”PUT /_emdash/api/menus/:name메뉴 삭제
섹션 제목: “메뉴 삭제”DELETE /_emdash/api/menus/:name메뉴 항목 추가
섹션 제목: “메뉴 항목 추가”POST /_emdash/api/menus/:name/itemsContent-Type: application/json
{ "type": "page", "referenceCollection": "pages", "referenceId": "page_about", "label": "About Us"}메뉴 항목 순서 재지정
섹션 제목: “메뉴 항목 순서 재지정”POST /_emdash/api/menus/:name/reorderContent-Type: application/json
{ "items": [ { "id": "item_1", "parentId": null, "sortOrder": 0 }, { "id": "item_2", "parentId": null, "sortOrder": 1 }, { "id": "item_3", "parentId": "item_2", "sortOrder": 0 } ]}분류 체계 엔드포인트
섹션 제목: “분류 체계 엔드포인트”분류 체계 정의 목록 조회
섹션 제목: “분류 체계 정의 목록 조회”GET /_emdash/api/taxonomies분류 체계 생성
섹션 제목: “분류 체계 생성”POST /_emdash/api/taxonomiesContent-Type: application/json
{ "name": "genre", "label": "Genres", "labelSingular": "Genre", "hierarchical": true, "collections": ["books", "movies"]}용어 목록 조회
섹션 제목: “용어 목록 조회”GET /_emdash/api/taxonomies/:name/terms용어 생성
섹션 제목: “용어 생성”POST /_emdash/api/taxonomies/:name/termsContent-Type: application/json
{ "slug": "tutorials", "label": "튜토리얼", "parentId": "term_abc", "description": "실전 가이드"}용어 업데이트
섹션 제목: “용어 업데이트”PUT /_emdash/api/taxonomies/:name/terms/:slug용어 삭제
섹션 제목: “용어 삭제”DELETE /_emdash/api/taxonomies/:name/terms/:slug항목 용어 설정
섹션 제목: “항목 용어 설정”POST /_emdash/api/content/:collection/:id/terms/:taxonomyContent-Type: application/json
{ "termIds": ["term_news", "term_featured"]}위젯 영역 엔드포인트
섹션 제목: “위젯 영역 엔드포인트”위젯 영역 목록 조회
섹션 제목: “위젯 영역 목록 조회”GET /_emdash/api/widget-areas위젯 영역 조회
섹션 제목: “위젯 영역 조회”GET /_emdash/api/widget-areas/:name위젯 영역 생성
섹션 제목: “위젯 영역 생성”POST /_emdash/api/widget-areasContent-Type: application/json
{ "name": "sidebar", "label": "메인 사이드바", "description": "게시물 페이지에 표시됩니다"}위젯 영역 삭제
섹션 제목: “위젯 영역 삭제”DELETE /_emdash/api/widget-areas/:name위젯 추가
섹션 제목: “위젯 추가”POST /_emdash/api/widget-areas/:name/widgetsContent-Type: application/json
{ "type": "content", "title": "소개", "content": [...]}위젯 업데이트
섹션 제목: “위젯 업데이트”PUT /_emdash/api/widget-areas/:name/widgets/:id위젯 삭제
섹션 제목: “위젯 삭제”DELETE /_emdash/api/widget-areas/:name/widgets/:id위젯 순서 재지정
섹션 제목: “위젯 순서 재지정”POST /_emdash/api/widget-areas/:name/reorderContent-Type: application/json
{ "widgetIds": ["widget_1", "widget_2", "widget_3"]}사용자 관리 엔드포인트
섹션 제목: “사용자 관리 엔드포인트”사용자 목록 조회
섹션 제목: “사용자 목록 조회”GET /_emdash/api/admin/usersGET /_emdash/api/admin/users?role=40GET /_emdash/api/admin/users?search=john사용자 조회
섹션 제목: “사용자 조회”GET /_emdash/api/admin/users/:id사용자 업데이트
섹션 제목: “사용자 업데이트”PATCH /_emdash/api/admin/users/:idContent-Type: application/json
{ "name": "John Doe", "role": 40}사용자 활성화
섹션 제목: “사용자 활성화”POST /_emdash/api/admin/users/:id/enable사용자 비활성화
섹션 제목: “사용자 비활성화”POST /_emdash/api/admin/users/:id/disable인증 엔드포인트
섹션 제목: “인증 엔드포인트”설정 상태
섹션 제목: “설정 상태”GET /_emdash/api/setup/status설정이 완료되었는지와 사용자가 존재하는지 여부를 반환합니다.
패스키 로그인
섹션 제목: “패스키 로그인”POST /_emdash/api/auth/passkey/optionsWebAuthn 인증 옵션을 가져옵니다.
POST /_emdash/api/auth/passkey/verifyContent-Type: application/json
{ "id": "credential-id", "rawId": "...", "response": {...}, "type": "public-key"}패스키를 확인하고 세션을 생성합니다.
매직 링크
섹션 제목: “매직 링크”POST /_emdash/api/auth/magic-link/sendContent-Type: application/json
{ "email": "user@example.com"}GET /_emdash/api/auth/magic-link/verify?token=xxx로그아웃
섹션 제목: “로그아웃”POST /_emdash/api/auth/logout현재 사용자
섹션 제목: “현재 사용자”GET /_emdash/api/auth/me사용자 초대
섹션 제목: “사용자 초대”POST /_emdash/api/auth/inviteContent-Type: application/json
{ "email": "newuser@example.com", "role": 30}패스키 관리
섹션 제목: “패스키 관리”GET /_emdash/api/auth/passkey사용자의 패스키 목록을 조회합니다.
POST /_emdash/api/auth/passkey/register/optionsPOST /_emdash/api/auth/passkey/register/verify새로운 패스키를 등록합니다.
PATCH /_emdash/api/auth/passkey/:idContent-Type: application/json
{ "name": "MacBook Pro"}패스키 이름을 변경합니다.
DELETE /_emdash/api/auth/passkey/:id패스키를 삭제합니다.
임포트 엔드포인트
섹션 제목: “임포트 엔드포인트”WordPress 내보내기 분석
섹션 제목: “WordPress 내보내기 분석”POST /_emdash/api/import/wordpress/analyzeContent-Type: multipart/form-data
file: <WXR file>WordPress 임포트 실행
섹션 제목: “WordPress 임포트 실행”POST /_emdash/api/import/wordpress/executeContent-Type: application/json
{ "analysisId": "...", "options": { "includeMedia": true, "includeTaxonomies": true, "includeMenus": true }}요청 제한
섹션 제목: “요청 제한”API 엔드포인트는 배포 구성에 따라 요청 제한이 적용될 수 있습니다. 제한이 적용되면 응답에 다음이 포함됩니다:
HTTP/1.1 429 Too Many RequestsRetry-After: 60CORS
섹션 제목: “CORS”이 API는 브라우저 요청을 위한 CORS를 지원합니다. 배포 시 허용된 출처를 구성하세요.