Skip to content
created by Aha00aAha00a at 2026-06-24
last modified by Aha00aAha00a at 2026-09-24
revision: 15

Api

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 인증 사용자로 페이지 이름변경/삭제
  • 저장된 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. 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": []
}

7. 페이지 저장

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로 기록됩니다. 웹 편집과 달리 알림을 보내지 않습니다(위 제한사항).

8. 페이지 이름변경

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로 기록됩니다.

9. 페이지 삭제

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를 반환합니다.

삭제 성공 시 페이지에 연결된 첨부파일도 웹 삭제와 같은 정책으로 삭제 처리합니다.

10. 최근 변경 조회

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 이후 변경만 조회
  • afterRevisionname으로 지정한 단일 페이지에서 해당 revision 초과 변경만 조회
  • includeMinorEdit0이면 minor edit 제외, 기본값은 1
  • includeViaApi0이면 API Key 저장 제외, 기본값은 1
  • limit — 최대 행 수, 기본값은 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"
    }
  ]
}

11. 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이 남기는 내려받기 기록입니다.

12. 변경 이력 표시와 필터

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/changeincludeViaApi 파라미터를 받습니다. 기본값은 0입니다.
  • Admin Recent Changes 화면에는 viaApi 포함/제외 토글과 minor edit, Via API 이모지 컬럼이 있습니다.
  • Admin Dashboard의 Recent Changes 요약 표도 minor edit와 API 편집을 함께 불러와, 같은 이모지 컬럼으로 표시합니다. 2026-09-13 전에는 둘을 빼고 불러와서 두 컬럼이 늘 비어 있었습니다.

13. 저장 Flow

자동화 도구는 아래 순서로 저장합니다.

  • GET /api/v1/page/*name으로 현재 본문과 revision을 읽습니다.
  • 본문을 수정합니다.
  • POST /api/v1/page/*name에 읽었던 revision과 수정된 전체 text를 함께 보냅니다.
  • 409 Conflict가 오면 최신 본문을 다시 읽고 변경 내용을 병합한 뒤 재시도합니다.

14. 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와 원인을 보고한다.

15. 에러 코드

코드

의미

400 Bad Request

JSON body 없음, revision·text 누락, 본문 변경 없음, 삭제에 confirm: true 없음, 이름변경에 name·newName 없음, since 형식 오류, name 없이 afterRevision 사용

401 Unauthorized

API Key 없음 또는 유효하지 않음

403 Forbidden

API Key 소유자에게 그 작업의 권한 없음

404 Not Found

읽기·이름변경·삭제 대상 페이지가 없음

409 Conflict

요청 revision이 최신 revision과 다름(응답에 latestRevision 포함), 또는 이름변경 대상 이름이 이미 있음

500 Internal Server Error

삭제 중 첨부파일 삭제 실패

16. 관련

17. See Also

17.2. Similar Pages

Similar pages by cosine similarity. Words after page name are term frequency.

  • Same Wiki
    • 82.58% Dev Api api(84:147), key(32:85), page(27:33), via(20:35), user(8:44), wiki(15:22), name(20:16), v1(16:19), aha(14:19), revision(19:8)
    • 54.15% Dev ApiControllers api(84:24), key(32:3), page(27:1), 페이지(19:6), wiki(15:5), v1(16:1), 저장(15:1), admin(3:12), 조회(11:2), bearer(11:1)
    • 41.95% Dev ApiResponse api(84:42), json(5:42), admin(3:33), page(27:8), revision(19:10), name(20:2), error(1:21), 페이지(19:2), v1(16:5), wiki(15:5)
    • 36.31% Dev Page api(84:4), page(27:30), key(32:1), name(20:10), 페이지(19:10), revision(19:6), via(20:1), wiki(15:6), minor(16:1), content(15:2)
    • 31.08% AhaWiki api(84:2), key(32:1), wiki(15:9), aha(14:10), via(20:2), name(20:1), revision(19:1), minor(16:2), ahawiki(15:2), edit(15:1)
    • 30.11% Dev Editor api(84:15), page(27:13), key(32:6), edit(15:20), aha(14:19), wiki(15:14), name(20:8), 저장(15:10), revision(19:4), 페이지(19:1)
  • Sister Wikis
    • 40.63% Aha00a:RecentChanges api(84:2), page(27:3), via(20:2), name(20:1), revision(19:1), minor(16:2), edit(15:1), wiki(15:1), changes(8:3), date(8:1)
    • 39.05% WhoHow:FrontPage api(84:2), page(27:2), via(20:2), name(20:1), revision(19:1), minor(16:2), edit(15:1), wiki(15:1), net(12:1), changes(8:3)
    • 36.99% DringDring:FrontPage api(84:2), page(27:2), via(20:2), name(20:1), revision(19:1), minor(16:2), edit(15:1), wiki(15:1), aha(14:1), changes(8:3)
    • 36.87% AhariseWiki:FrontPage api(84:2), page(27:2), via(20:2), name(20:1), revision(19:1), minor(16:2), wiki(15:2), edit(15:1), changes(8:3), 변경(9:1)
    • 33.71% Millpoo:FrontPage api(84:2), page(27:2), via(20:2), name(20:1), revision(19:1), minor(16:2), wiki(15:3), ahawiki(15:1), edit(15:1), aha(14:2)
    • 31.73% Aha00a:PlantUML api(84:30), include(4:18), content(15:1), aha(14:1), git(3:11), sync(7:3), front(6:2), application(4:2), pages(4:1), 보고(3:1)
    • 31.16% Aha00a:FrontPage api(84:2), page(27:2), via(20:2), name(20:1), revision(19:1), minor(16:2), wiki(15:3), edit(15:1), aha(14:2), changes(8:3)

17.3. Adjacent Pages

Control
≤ 32
all
1.0x
1.0x
80
-120
ON
Metrics
Nodes(visible/total)0/0
Links(visible/total)0/0
Avg degree0.00
Depth coverage0
Queue(fetch/graph)0 / 0
Zoom(scale)1.00x
Ctrl/⌘ + Scroll: Zoom
Root 1-hop 2-hop+