AhaWiki 페이지를 외부 사용자, 자동화 도구, AI 에이전트가 API Key로 읽고 저장하기 위한 API입니다.
AhaWiki API는 세션 쿠키 대신 Authorization: Bearer <key> 헤더를 사용합니다.
AhaWiki API 요청에는 CSRF token과 reCAPTCHA가 필요하지 않습니다.
읽기/쓰기 endpoint path는 /api/v1/ prefix를 사용합니다.
1. 지원 기능
- API Key 인증 사용자로 페이지 읽기
- API Key 인증 사용자로 페이지 저장
- API Key 인증 사용자로 페이지 목록/메타 조회
- API Key 인증 사용자로 이름·본문 검색
- API Key 인증 사용자로 최근 변경 조회
- API Key 인증 사용자로 페이지 이름변경/삭제
- 저장된 revision에
viaApi = true와 저장에 사용한 API Key(userApiKey) 기록 /api/v1/changes응답과 History·RecentChanges 화면에viaApi와 key 이름(userApiKeyName) 표시 — 아래 변경 이력 표시와 필터
2. 제한사항
- API로 저장·이름변경·삭제하면 텔레그램 알림이 가지 않습니다. 그 페이지를 열어 둔 브라우저의 실시간 갱신 알림은 API 저장에도 갑니다.
3. 인증
AhaWiki API 호출에는 아래 헤더를 넣습니다.
Authorization: Bearer ahawiki_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
API Key는 생성 화면에서 한 번만 plain text로 표시됩니다.
이후 목록 조회에서는 keyPrefix만 볼 수 있고 원본 key는 다시 조회할 수 없습니다.
API Key는 Account Settings의 API Keys 섹션에서 생성하고 폐기할 수 있습니다.
키가 유출되면 Account Settings에서 폐기해야 합니다.
이 문서는 Authorization: Bearer <api-key>로 호출하는 API만 다룹니다.
브라우저 세션과 CSRF token이 필요한 Account/Admin API는 공개 API로 다루지 않습니다.
4. 페이지 읽기
curl https://ahawiki.net/api/v1/page/FrontPage \ -H "Authorization: Bearer <api-key>"
응답:
{ "name": "FrontPage", "revision": 12, "content": "= FrontPage\n...", "dateTime": "2026-06-24T10:00:00", "isMinorEdit": false, "viaApi": false, "userApiKeyName": null, "contentHash": "sha256:..." }
권한은 API Key 소유자의 기존 WikiPermission을 따릅니다.
읽기 권한이 없으면 403 Forbidden을 반환합니다.
5. 페이지 목록/메타 조회
curl "https://ahawiki.net/api/v1/pages?prefix=ToDo&limit=100" \ -H "Authorization: Bearer <api-key>"
응답:
{ "pages": [ { "name": "ToDo", "revision": 81, "dateTime": "2026-06-24T22:00:00", "isMinorEdit": false, "viaApi": true, "userApiKeyName": "AhaWikiDoc", "size": 3223, "contentHash": "sha256:..." } ] }
contentHash는 전체 본문을 내려받지 않고 local/remote 차이를 빠르게 비교하기 위한 SHA-256 hash입니다.
응답은 API Key 소유자가 읽을 수 있는 페이지로 제한됩니다.
6. 검색
curl "https://ahawiki.net/api/v1/search?q=OnThisDay&limit=20" \ -H "Authorization: Bearer <api-key>"
응답:
{ "q": "OnThisDay", "truncated": false, "pages": [ { "name": "MacroOnThisDay", "dateTime": "2026-10-25T14:01:23", "snippet": "…같은 월·일에 날짜 속성이 걸린 페이지를…" } ] }
검색 화면(/search)과 같은 질의입니다 — 페이지 이름이나 본문에 q 가 들어 있는 페이지의 최신 리비전을, 대소문자를 가리지 않고 찾습니다. 같은 읽기 권한 필터를 거치므로 API Key 소유자가 브라우저에서 검색했을 때와 같은 페이지만 나옵니다. 최신순이고, snippet 은 첫 번째로 맞은 곳 앞뒤의 평문입니다(HTML 표시가 없습니다 — JSON 을 읽는 쪽이 그대로 쓰게). 이름에서만 맞았으면 본문의 앞부분이 나옵니다.
limit의 기본값은 20, 상한은 100입니다. 위키를 통째로 내려받는 용도가 아니라 «어느 페이지를 열지» 찾는 용도이고, 이름 접두사로 훑는 것은/api/v1/pages가 합니다.truncated가true이면limit보다 많이 맞았다는 뜻입니다.q가 비어 있으면400입니다.- 전문 검색 색인이 아니라
LIKE검색입니다. 페이지가 아주 많은 위키에서 느려지면 그때 색인을 봅니다.
7. Batch 페이지 메타 조회
curl -X POST https://ahawiki.net/api/v1/pages/metadata \ -H "Authorization: Bearer <api-key>" \ -H "Content-Type: application/json" \ -d '{"names":["Api","Dev Api","MissingPage"]}'
응답:
{ "pages": [ { "name": "Api", "revision": 1, "dateTime": "2026-06-24T22:20:29", "isMinorEdit": false, "viaApi": true, "userApiKeyName": "AhaWikiDoc", "size": 5548, "contentHash": "sha256:..." } ], "missing": ["MissingPage"], "forbidden": [] }
8. 페이지 저장
curl -X POST https://ahawiki.net/api/v1/page/FrontPage \ -H "Authorization: Bearer <api-key>" \ -H "Content-Type: application/json" \ -d '{ "revision": 12, "text": "= FrontPage\nupdated content", "comment": "Update via API", "minorEdit": false }'
요청 필드:
revision— 저장 기준 revision. 최신 revision과 다르면 저장하지 않습니다.text— 저장할 전체 페이지 본문.comment— 저장 comment. 생략하면 빈 문자열입니다.minorEdit— minor edit 여부. 생략하면false입니다.
응답:
{ "name": "FrontPage", "revision": 13, "dateTime": "2026-06-24T10:01:00" }
저장 성공 시 새 revision은 viaApi = true로 기록됩니다. 웹 편집과 달리 텔레그램 알림은 보내지 않습니다(위 제한사항).
9. 페이지 이름변경
curl -X POST https://ahawiki.net/api/v1/rename \ -H "Authorization: Bearer <api-key>" \ -H "Content-Type: application/json" \ -d '{ "name": "OldPage", "newName": "NewPage", "revision": 3, "comment": "Rename via API" }'
요청 revision이 최신 revision과 다르면 409 Conflict를 반환합니다.
대상 페이지가 이미 있으면 409 Conflict를 반환합니다.
성공하면 기존 페이지 이름을 newName으로 바꾸고, 기존 이름에는 redirect page를 생성합니다.
redirect revision은 viaApi = true로 기록됩니다.
10. 페이지 삭제
curl -X DELETE https://ahawiki.net/api/v1/page/OldPage \ -H "Authorization: Bearer <api-key>" \ -H "Content-Type: application/json" \ -d '{ "revision": 3, "confirm": true }'
삭제는 되돌리기 어려운 작업이므로 confirm: true가 필요합니다.
요청 revision이 최신 revision과 다르면 409 Conflict를 반환합니다.
삭제 성공 시 페이지에 연결된 첨부파일도 웹 삭제와 같은 정책으로 삭제 처리합니다.
11. 최근 변경 조회
curl "https://ahawiki.net/api/v1/changes?prefix=ToDo&since=2026-06-24T00:00:00&limit=100" \ -H "Authorization: Bearer <api-key>"
query parameter:
name— 특정 page name만 조회.afterRevision을 사용할 때 필요합니다.prefix— page name prefix 필터since— ISO-8601 local date-time 이후 변경만 조회afterRevision—name으로 지정한 단일 페이지에서 해당 revision 초과 변경만 조회includeMinorEdit—0이면 minor edit 제외, 기본값은1includeViaApi—0이면 API Key 저장 제외, 기본값은1limit— 최대 행 수, 기본값은100
revision은 페이지별 번호이므로 afterRevision은 전체 sync cursor로 사용할 수 없습니다.
전체 동기화는 since와 페이지별 metadata 비교를 함께 사용합니다.
응답:
{ "changes": [ { "name": "Api", "revision": 2, "dateTime": "2026-06-24T22:00:00", "comment": "AhaWikiDoc sync Api", "isMinorEdit": false, "viaApi": true, "userApiKeyName": "AhaWikiDoc" } ] }
12. AhaWikiDoc sync 권장 방식
문서 동기화 도구는 서버에 별도 sync state를 저장하지 않고 local manifest를 갱신하는 방식을 권장합니다.
GET /api/v1/pages로 원격 페이지의revision,dateTime,contentHash를 조회합니다.- local manifest의 마지막 동기화 시각 또는 page별 revision과 비교합니다.
- 변경 후보만
GET /api/v1/page/*name으로 본문을 내려받아 local file과 비교합니다. - local에서 검토/커밋된 문서가 원격보다 최신이면
POST /api/v1/page/*name으로 저장합니다. - 원격이 최신이면 local file을 갱신합니다.
- 양쪽이 모두 바뀐 경우 자동 덮어쓰기를 하지 말고 병합하거나 사용자에게 확인합니다.
- 저장/가져오기 완료 후 local manifest에
lastSyncedAt, page별revision,dateTime,contentHash를 기록합니다.
이 저장소의 참조 구현은 2·3·5·7번을 하지 않습니다. scripts/sync.ahawiki.net.mjs는 별도 manifest 대신 git 히스토리를 마지막 동기화 기록으로 쓰고, 본문을 내려받아 비교하지 않고 목록의 contentHash만 비교합니다 — 원격 본문이 그 파일의 최근 커밋 40개 중 예전 버전과 같으면 로컬이 앞선 것으로 보고 --apply일 때 저장하고, 그렇지 않으면 브라우저에서 편집된 것으로 보고 diverged로 알리기만 합니다. 로컬 파일은 바꾸지 않습니다 — diverged는 사람이 병합해 커밋하고, 로컬에 없는 페이지는 download:ahawiki.net으로 받습니다. 문서가 이미 git 으로 관리되므로 같은 사실을 manifest 에 한 번 더 적으면 그 둘이 갈라지기 때문입니다. manifest 방식은 문서가 git 밖에 있는 도구에 유효합니다.
docs/ahawiki.net/manifest.json은 sync state가 아니라 download:ahawiki.net이 남기는 내려받기 기록입니다.
13. 변경 이력 표시와 필터
API Key로 저장한 revision은 viaApi = true로 기록되고, 저장에 사용한 key는 userApiKey로 기록됩니다.
응답의 userApiKeyName은 저장에 쓴 key의 현재 이름입니다. 웹에서 저장한 revision은 null입니다. key를 폐기해도 이름은 그대로 나옵니다 — 폐기는 key를 못 쓰게 할 뿐 기록을 지우지 않습니다.
- History 화면에는 minor edit, Via API 이모지 컬럼과
Show ViaApi필터가 있고, Via API 편집에는 key 이름이 함께 표시됩니다. RecentChanges매크로에는Include via API edits토글과 minor edit, Via API 이모지 컬럼이 있습니다. 토글은 처음에 켜져 있습니다(MacroRecentChanges)./api/change는includeViaApi파라미터를 받습니다. 기본값은0입니다.- Admin Recent Changes 화면에는 viaApi 포함/제외 토글과 minor edit, Via API 이모지 컬럼이 있습니다.
- Admin Dashboard의 Recent Changes 요약 표도 minor edit와 API 편집을 함께 불러와, 같은 이모지 컬럼으로 표시합니다. 2026-09-13 전에는 둘을 빼고 불러와서 두 컬럼이 늘 비어 있었습니다.
14. 저장 Flow
자동화 도구는 아래 순서로 저장합니다.
GET /api/v1/page/*name으로 현재 본문과revision을 읽습니다.- 본문을 수정합니다.
POST /api/v1/page/*name에 읽었던 revision과 수정된 전체 text를 함께 보냅니다.409 Conflict가 오면 최신 본문을 다시 읽고 변경 내용을 병합한 뒤 재시도합니다.
15. AI 자동화 프롬프트 예시
아래 프롬프트를 AI 코딩 에이전트나 자동화 도구에 전달하면 AhaWiki API로 페이지를 읽고 수정하게 할 수 있습니다.
<api-key>, <page-name>, <task>는 실제 값으로 바꿉니다.
너는 AhaWiki 문서를 수정하는 자동화 에이전트다. 인증: - 모든 AhaWiki API 요청에 `Authorization: Bearer <api-key>` 헤더를 넣어라. - CSRF token, session cookie, reCAPTCHA는 AhaWiki API에 필요 없다. - API Key를 로그, 문서 본문, 저장 comment에 노출하지 마라. 대상: - Base URL: https://ahawiki.net - Page: <page-name> - 작업: <task> 읽기: 1. `GET https://ahawiki.net/api/v1/page/<url-encoded-page-name>`를 호출한다. 2. 응답의 `revision`과 `content`를 저장한다. 3. `403`이면 권한 없음으로 중단하고, `404`이면 페이지 없음으로 보고한다. 수정: 1. 기존 `content`를 기준으로 필요한 부분만 바꾼 전체 본문을 만든다. 2. 관련 없는 내용, 포맷, 줄바꿈은 가능한 유지한다. 3. 저장 comment는 사람이 이해할 수 있게 짧게 쓴다. 4. 사소한 포맷/오타 수정이면 `minorEdit: true`, 의미 있는 내용 변경이면 `minorEdit: false`로 보낸다. 저장: `POST https://ahawiki.net/api/v1/page/<url-encoded-page-name>`에 아래 JSON을 보낸다. { "revision": <읽은 revision>, "text": "<수정된 전체 본문>", "comment": "<저장 comment>", "minorEdit": false } 충돌 처리: - `409 Conflict`가 오면 최신 페이지를 다시 읽고 내 변경사항을 최신 본문에 병합한 뒤 한 번 더 저장한다. - 병합이 애매하면 저장하지 말고 충돌 내용을 보고한다. 완료 보고: - 저장 성공 시 새 revision을 보고한다. - 저장하지 못하면 HTTP status와 원인을 보고한다.
16. 에러 코드
코드 | 의미 |
|---|---|
| JSON body 없음, |
| API Key 없음 또는 유효하지 않음 |
| API Key 소유자에게 그 작업의 권한 없음 |
| 읽기·이름변경·삭제 대상 페이지가 없음 |
| 요청 revision이 최신 revision과 다름(응답에 |
| 삭제 중 첨부파일 삭제 실패 |
18. See Also
18.2. Similar Pages
Similar pages by cosine similarity. Words after page name are term frequency.