# Work is 1 REST API v1

Work is 1의 REST API는 외부 시스템(AI 워커, 자동화 도구, 사내 봇 등)이 워크스페이스의 테스크를 안전하게 조회·진행할 수 있도록 설계되었습니다. **테스크의 종결(완료/취소/거절)은 사람만 가능**하며, API는 그 외 모든 작업을 수행할 수 있습니다.

> Base URL: `https://w1.nola.kr/api/v1`
> 인증: Bearer 토큰 (워크스페이스 API 키)
> Rate limit: 분당 **60** 요청 / 키
> 마지막 갱신: 2026-05-29

---

## 1. 인증

워크스페이스 소유자가 `워크스페이스 설정 → API 키`에서 발급합니다. 발급 시 평문이 1회만 노출되며, 이후에는 SHA-256 해시로만 저장됩니다.

```
Authorization: Bearer w1_<hex 48자>
```

**키 포맷**: `w1_` 접두 + 48자 hex
**스코프**: 발급한 워크스페이스 단일 — 다른 워크스페이스 자원에는 접근 불가
**철회**: 워크스페이스 설정에서 즉시 revoke 가능 (반영 즉시)

`Authorization` 헤더는 Apache 환경에서 PHP로 전달되지 않을 수 있으므로, `.htaccess`에 다음을 추가해야 합니다 (서버에 이미 적용 완료):

```
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
```

---

## 2. Rate limit

- 키별로 분당 **60 요청** 제한 (DB 윈도우 기반)
- 초과 시 `429 Too Many Requests` + `Retry-After` 헤더 반환
- 1시간 이전 윈도우는 자동 청소

---

## 3. 정책: 종결은 사람만 (★)

```
PATCH /api/v1/tasks/{id}/status  with to=completed|canceled|rejected
→ 403 { "error": { "code": "human_only", "message": "..." } }
```

- 등록자(사람)만이 테스크를 종결할 수 있다는 원칙을 API에도 그대로 반영
- AI 워커는 진행 시작 / 검토 요청 / 코멘트 등록 / 첨부 다운로드 등은 자유롭게 수행 가능
- 진행/검토 흐름: `pending ↔ in_progress`, `in_progress → review`, `review → in_progress`

---

## 4. AI 친화 응답 필드

같은 키로 호출하는 AI 클라이언트가 본인이 누구인지 식별하기 쉽게, 모든 응답에 다음 플래그를 포함합니다.

| 필드 | 위치 | 의미 |
|------|------|------|
| `is_me` | task / history.entry / comment | 해당 자원이 키 발급자(=동작 주체)에게 귀속되는지 |
| `is_registrant` | task | 키 발급자가 등록자인지 |
| `is_assignee` | task | 키 발급자가 담당자인지 |
| `source` | comment | `web` / `api` / `system` — 코멘트 출처 |

웹 UI는 source=api 코멘트에 "API" 칩을 표시합니다.

---

## 5. 엔드포인트

### 5.1 `GET /me`

```bash
curl -H "Authorization: Bearer $KEY" https://w1.nola.kr/api/v1/me
```

응답: 인증된 키의 발급자(사용자) + 워크스페이스 + 정책 안내.

### 5.2 `GET /tasks`

쿼리:
- `scope` — `assigned` (기본) / `registered` / `all`
- `status` — `todo` (기본 — `pending`+`in_progress` 만, AI 워커의 실제 작업 큐. `review` 는 사람 차례, `rejected` 는 사람 판단) / `open` (`completed`/`canceled` 만 제외) / `all` / `pending` / `in_progress` / `review` / `completed` / `rejected` / `canceled`
- `project_id` — 특정 프로젝트로 좁히기
- `page`, `per` — 페이지네이션

```bash
curl -H "Authorization: Bearer $KEY" \
  "https://w1.nola.kr/api/v1/tasks?scope=assigned&status=todo"
```

응답:
```json
{
  "data": [
    {
      "id": 4, "title": "...", "status": "pending", "priority": "high",
      "due_at": "2026-05-30 18:00:00",
      "project": { "id": 1, "name": "...", "slug": "..." },
      "registrant_id": 2, "assignee_id": 3,
      "is_mine": true, "is_registrant": false, "is_assignee": true,
      "web_url": "https://w1.nola.kr/w/.../t/4"
    }
  ],
  "meta": { "total": 1, "page": 1, "per_page": 50, "pages": 1 }
}
```

### 5.3 `GET /tasks/{id}`

상세: 위 필드 + `content`, `registrant`, `assignee`, `history`, `attachments`, `comments`.

- `history` 각 entry는 `changed_by: {id,name}` + `is_me`
- `comments` 각 entry는 `author: {id,name}` + `is_me` + `source`
- `attachments`: `type` (file|url) / `name` / `mime` / `size` / `uploaded_by` / `download_url`

### 5.4 `GET /tasks/{id}/attachments/{aid}/download`

Bearer 인증 필요. 파일은 스트림 응답, URL 첨부는 JSON으로 원본 URL 반환.

```bash
curl -H "Authorization: Bearer $KEY" -o spec.pdf \
  https://w1.nola.kr/api/v1/tasks/4/attachments/1/download
```

### 5.5 `POST /tasks/{id}/comments`

```json
{ "content": "처리 완료. @폴 검토 부탁드려요" }
```

- `@닉네임` 멘션 자동 추출 + 알림 트리거
- `source=api`로 저장 → 웹 UI에서 "API" 칩 표시

### 5.6 `PATCH /tasks/{id}/status`

```json
{ "to": "in_progress", "reason": "(선택) 변경 사유" }
```

- 허용: `pending ↔ in_progress`, `in_progress → review`, `review → in_progress` (등록자/admin)
- **차단**: `completed` / `canceled` / `rejected` → **403 `human_only`**

---

## 6. AI 워커 시나리오 (예시)

```
1. GET /tasks?scope=assigned&status=todo       — 내가 처리할 일감 큐 (pending + in_progress)
2. GET /tasks/{id}                              — 요청사항 + 히스토리 확인
3. GET /tasks/{id}/attachments/{aid}/download   — 첨부파일 받기
4. (외부에서 처리 수행)
5. POST /tasks/{id}/comments                   — 처리 결과 보고
6. PATCH /tasks/{id}/status (to=review)         — 검토 요청
                                                  ↑ 종결은 사람이 직접
```

---

## 7. 에러 응답 포맷

```json
{ "error": { "code": "human_only", "message": "..." } }
```

| code | HTTP | 설명 |
|------|------|------|
| `unauthorized`     | 401 | Bearer 토큰 없음/만료 |
| `forbidden`        | 403 | 키 스코프 외 자원 |
| `human_only`       | 403 | 종결성 상태 전이는 사람만 |
| `not_found`        | 404 | 자원 없음 |
| `rate_limited`     | 429 | 분당 한도 초과 |
| `validation`       | 422 | 입력값 오류 |
| `internal`         | 500 | 서버 오류 (`ref` 동봉) |

---

## 8. 자주 묻는 질문

**Q. AI가 테스크를 완료처리할 수 없는 이유는?**
사람의 책임 영역 보호를 위해 의도된 정책입니다. AI는 처리·검토 요청까지, 최종 종결은 등록자가 수행합니다.

**Q. 키를 잃어버렸어요.**
복구 불가입니다. 워크스페이스 설정에서 기존 키를 revoke 하고 새로 발급하세요.

**Q. 멘션 알림이 안 와요.**
멘션 대상자의 알림 설정에서 `mention` 채널이 켜져 있는지 확인하세요. 본인이 본인을 멘션하면 알림이 발송되지 않습니다.

---

© 2026 Work is 1 · 본 문서는 `/docs/api`(HTML) 및 `/docs/api.md`(MD 다운로드)에서 동일 내용을 제공합니다.
