# 🌽 그라운드 학급 미션 조회 API 가이드

👉🏻 그라운드에서 학급 총 포인트와 학급 미션 현황을 조회하는 API 기능을 설명합니다.

## 목차

1. [시작하기](https://#%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0)

2. [API 키 발급](https://#api-%ED%82%A4-%EB%B0%9C%EA%B8%89)

3. [인증 방식](https://#%EC%9D%B8%EC%A6%9D-%EB%B0%A9%EC%8B%9D)

4. [학급 미션 조회 API](https://#%ED%95%99%EA%B8%89-%EB%AF%B8%EC%85%98-%EC%A1%B0%ED%9A%8C-api)

5. [응답 데이터 상세](https://#%EC%9D%91%EB%8B%B5-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%83%81%EC%84%B8)

6. [에러 처리](https://#%EC%97%90%EB%9F%AC-%EC%B2%98%EB%A6%AC)

7. [코드 예제](https://#%EC%BD%94%EB%93%9C-%EC%98%88%EC%A0%9C)

8. [제한 사항](https://#%EC%A0%9C%ED%95%9C-%EC%82%AC%ED%95%AD)

---

## 시작하기

그라운드 학급 미션 조회 API를 사용하면 외부 애플리케이션에서 다음 정보를 한 번에 조회할 수 있습니다.

- 해당 학급의 총 누적 포인트

- 해당 학급의 미션 목록

- 미션 달성 수, 달성률, 다음 미션

### 기본 정보

- **Base URL**: `https://growndcard.com`

- **프로토콜**: HTTPS

- **인증 방식**: API Key (`X-API-Key` 헤더)

- **권장 권한**: `readClassMissions`

> 참고: 기존에 발급된 일부 API 키는 `readStudents` 권한으로도 학급 미션 조회가 가능할 수 있습니다. 신규 키는 `readClassMissions` 권한을 별도로 설정하는 것을 권장합니다.

---

## API 키 발급

### 1. 그라운드에 로그인

교사 계정으로 [그라운드](https://growndcard.com)에 로그인합니다.

### 2. 내 정보 페이지 이동

우측 상단 프로필 → **내 정보** 클릭

### 3. API 키 관리 탭

**API 키 관리** 탭을 선택합니다.

### 4. 새 API 키 생성

1. **"새 API 키 생성"** 버튼 클릭

2. 다음 정보 입력

- **API 키 이름**: 애플리케이션 이름

- **만료 기간**: 무제한 또는 30일, 90일, 180일, 1년

- **권한 설정**:

    - ✅ `readClassMissions` 권한 권장

- **호출 제한**: 기본값 분당 60회, 일일 500회

1. **"API 키 생성"** 클릭

### 5. API 키 저장

⚠️ API 키는 **한 번만 표시**됩니다.

```
sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2
```

반드시 안전한 곳에 복사하여 보관하세요.

---

## 인증 방식

모든 API 요청에는 `X-API-Key` 헤더가 필요합니다.

```
X-API-Key: sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2
```

---

## 학급 미션 조회 API

### 엔드포인트

```
GET /api/v1/classes/{classId}/missions
```

### URL 파라미터

| 파라미터 | 타입 | 설명 | 예시 |
| --- | --- | --- | --- |
| `classId` | string | 클래스 ID | `NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2` |

> 💡 **classId 확인 방법**: 그라운드 → 클래스 관리 → 클래스 카드에서 "ID" 확인

### 요청 헤더

| 헤더 | 값 | 필수 |
| --- | --- | --- |
| `X-API-Key` | 발급받은 API 키 | ✅ |

### 동작 방식

- 학급의 모든 학생 `totalPoints`를 합산해 `classTotalPoints`를 계산합니다.

- `missions` 서브컬렉션의 미션을 `targetPoint` 오름차순으로 조회합니다.

- 현재 총점 이상에 도달한 미달성 미션은 자동으로 달성 처리한 뒤 결과를 반환합니다.

### 성공 응답 예시

```
{
  "success": true,
  "data": {
    "classId": "NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2",
    "classTotalPoints": 1820,
    "missionSummary": {
      "totalMissions": 4,
      "achievedMissions": 2,
      "pendingMissions": 2,
      "achievementRate": 50,
      "status": "in_progress",
      "nextMission": {
        "missionId": "mission_003",
        "targetPoint": 2000,
        "reward": "영화 보기",
        "remainingPoints": 180
      }
    },
    "missions": [
      {
        "missionId": "mission_001",
        "targetPoint": 500,
        "reward": "간식 데이",
        "achieved": true,
        "achievedAt": "2026-03-20T02:10:00.000Z",
        "createdAt": "2026-03-01T01:00:00.000Z",
        "updatedAt": "2026-03-20T02:10:00.000Z"
      },
      {
        "missionId": "mission_002",
        "targetPoint": 1000,
        "reward": "자율 놀이 시간",
        "achieved": true,
        "achievedAt": "2026-03-25T02:10:00.000Z",
        "createdAt": "2026-03-05T01:00:00.000Z",
        "updatedAt": "2026-03-25T02:10:00.000Z"
      },
      {
        "missionId": "mission_003",
        "targetPoint": 2000,
        "reward": "영화 보기",
        "achieved": false,
        "achievedAt": null,
        "createdAt": "2026-03-10T01:00:00.000Z",
        "updatedAt": null
      }
    ]
  },
  "message": "학급 미션 현황 조회에 성공했습니다."
}
```

---

## 응답 데이터 상세

### 최상위 데이터

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `classId` | string | 클래스 ID |
| `classTotalPoints` | number | 학급 전체 학생의 총 포인트 합계 |
| `missionSummary` | object | 미션 요약 정보 |
| `missions` | array | 미션 목록 |

### `missionSummary`

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `totalMissions` | number | 전체 미션 개수 |
| `achievedMissions` | number | 달성한 미션 개수 |
| `pendingMissions` | number | 남은 미션 개수 |
| `achievementRate` | number | 달성률 (0~100) |
| `status` | string | `empty`, `in_progress`, `completed` |
| `nextMission` | object or null | 다음 목표 미션 정보 |

### `nextMission`

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `missionId` | string | 다음 미션 ID |
| `targetPoint` | number | 목표 포인트 |
| `reward` | string | 달성 보상 설명 |
| `remainingPoints` | number | 다음 목표까지 남은 포인트 |

### `missions` 배열 각 항목

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `missionId` | string | 미션 문서 ID |
| `targetPoint` | number | 목표 포인트 |
| `reward` | string | 달성 보상 |
| `achieved` | boolean | 달성 여부 |
| `achievedAt` | string or null | 달성 시각 |
| `createdAt` | string or null | 생성 시각 |
| `updatedAt` | string or null | 수정 시각 |

---

## 에러 처리

### 에러 응답 형식

```
{
  "success": false,
  "error": {
    "code": "error_code",
    "message": "에러 메시지",
    "details": {}
  }
}
```

### 에러 코드

| 상태 코드 | 에러 코드 | 설명 | 해결 방법 |
| --- | --- | --- | --- |
| 400 | `invalid_class_id` | 클래스 ID가 제공되지 않음 | classId 확인 |
| 401 | `unauthorized` | API 키가 없거나 유효하지 않음 | API 키와 헤더 확인 |
| 403 | `forbidden` | 해당 클래스 접근 권한 없음 | classId 권한 확인 |
| 403 | `insufficient_permissions` | 학급 미션 조회 권한이 없음 | `readClassMissions` 권한 확인 |
| 404 | `class_not_found` | 클래스를 찾을 수 없음 | classId 확인 |
| 429 | `rate_limit_exceeded` | 호출 제한 초과 | 잠시 후 재시도 |
| 500 | `internal_error` | 서버 내부 오류 | 잠시 후 재시도 |

### 에러 응답 예시

```
{
  "success": false,
  "error": {
    "code": "insufficient_permissions",
    "message": "학급 미션 조회 권한이 없습니다.",
    "details": {
      "requiredPermission": "readClassMissions"
    }
  }
}
```

---

## 코드 예제

### cURL

```
curl -X GET \
  "https://growndcard.com/api/v1/classes/NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2/missions" \
  -H "X-API-Key: sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2"
```

### JavaScript (Node.js)

```
const fetch = require('node-fetch');

const API_KEY = 'sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2';
const BASE_URL = 'https://growndcard.com';
const CLASS_ID = 'NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2';

async function getClassMissionStatus() {
  const response = await fetch(
    `${BASE_URL}/api/v1/classes/${CLASS_ID}/missions`,
    {
      method: 'GET',
      headers: {
        'X-API-Key': API_KEY
      }
    }
  );

  const data = await response.json();

  if (!response.ok) {
    throw new Error(data.error?.message || 'API 호출 실패');
  }

  return data.data;
}

getClassMissionStatus()
  .then(result => {
    console.log('학급 총 포인트:', result.classTotalPoints);
    console.log('달성률:', result.missionSummary.achievementRate);
    console.log('다음 미션:', result.missionSummary.nextMission);
  })
  .catch(error => console.error('에러:', error));
```

### Python

```
import requests

API_KEY = 'sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2'
BASE_URL = 'https://growndcard.com'
CLASS_ID = 'NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2'

def get_class_mission_status():
    response = requests.get(
        f'{BASE_URL}/api/v1/classes/{CLASS_ID}/missions',
        headers={
            'X-API-Key': API_KEY
        }
    )

    response.raise_for_status()
    return response.json()['data']

result = get_class_mission_status()
print('학급 총 포인트:', result['classTotalPoints'])
print('미션 달성률:', result['missionSummary']['achievementRate'])
```

---

## 제한 사항

- 교사 계정당 API 키 최대 3개 생성 가능

- 분당 최대 60회, 일일 최대 500회 호출 가능

- API 키는 생성 시 한 번만 표시됨

- 학급 접근 권한이 있는 클래스만 조회 가능

👉🏻 그라운드에서 학급 총 포인트와 학급 미션 현황을 조회하는 API 기능을 설명합니다.

## 목차

1. [시작하기](https://#%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0)

2. [API 키 발급](https://#api-%ED%82%A4-%EB%B0%9C%EA%B8%89)

3. [인증 방식](https://#%EC%9D%B8%EC%A6%9D-%EB%B0%A9%EC%8B%9D)

4. [학급 미션 조회 API](https://#%ED%95%99%EA%B8%89-%EB%AF%B8%EC%85%98-%EC%A1%B0%ED%9A%8C-api)

5. [응답 데이터 상세](https://#%EC%9D%91%EB%8B%B5-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%83%81%EC%84%B8)

6. [에러 처리](https://#%EC%97%90%EB%9F%AC-%EC%B2%98%EB%A6%AC)

7. [코드 예제](https://#%EC%BD%94%EB%93%9C-%EC%98%88%EC%A0%9C)

8. [제한 사항](https://#%EC%A0%9C%ED%95%9C-%EC%82%AC%ED%95%AD)

---

## 시작하기

그라운드 학급 미션 조회 API를 사용하면 외부 애플리케이션에서 다음 정보를 한 번에 조회할 수 있습니다.

- 해당 학급의 총 누적 포인트

- 해당 학급의 미션 목록

- 미션 달성 수, 달성률, 다음 미션

### 기본 정보

- **Base URL**: `https://growndcard.com`

- **프로토콜**: HTTPS

- **인증 방식**: API Key (`X-API-Key` 헤더)

- **권장 권한**: `readClassMissions`

> 참고: 기존에 발급된 일부 API 키는 `readStudents` 권한으로도 학급 미션 조회가 가능할 수 있습니다. 신규 키는 `readClassMissions` 권한을 별도로 설정하는 것을 권장합니다.

---

## API 키 발급

### 1. 그라운드에 로그인

교사 계정으로 [그라운드](https://growndcard.com)에 로그인합니다.

### 2. 내 정보 페이지 이동

우측 상단 프로필 → **내 정보** 클릭

### 3. API 키 관리 탭

**API 키 관리** 탭을 선택합니다.

### 4. 새 API 키 생성

1. **"새 API 키 생성"** 버튼 클릭

2. 다음 정보 입력

- **API 키 이름**: 애플리케이션 이름

- **만료 기간**: 무제한 또는 30일, 90일, 180일, 1년

- **권한 설정**:

    - ✅ `readClassMissions` 권한 권장

- **호출 제한**: 기본값 분당 60회, 일일 500회

1. **"API 키 생성"** 클릭

### 5. API 키 저장

⚠️ API 키는 **한 번만 표시**됩니다.

```
sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2
```

반드시 안전한 곳에 복사하여 보관하세요.

---

## 인증 방식

모든 API 요청에는 `X-API-Key` 헤더가 필요합니다.

```
X-API-Key: sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2
```

---

## 학급 미션 조회 API

### 엔드포인트

```
GET /api/v1/classes/{classId}/missions
```

### URL 파라미터

| 파라미터 | 타입 | 설명 | 예시 |
| --- | --- | --- | --- |
| `classId` | string | 클래스 ID | `NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2` |

> 💡 **classId 확인 방법**: 그라운드 → 클래스 관리 → 클래스 카드에서 "ID" 확인

### 요청 헤더

| 헤더 | 값 | 필수 |
| --- | --- | --- |
| `X-API-Key` | 발급받은 API 키 | ✅ |

### 동작 방식

- 학급의 모든 학생 `totalPoints`를 합산해 `classTotalPoints`를 계산합니다.

- `missions` 서브컬렉션의 미션을 `targetPoint` 오름차순으로 조회합니다.

- 현재 총점 이상에 도달한 미달성 미션은 자동으로 달성 처리한 뒤 결과를 반환합니다.

### 성공 응답 예시

```
{
  "success": true,
  "data": {
    "classId": "NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2",
    "classTotalPoints": 1820,
    "missionSummary": {
      "totalMissions": 4,
      "achievedMissions": 2,
      "pendingMissions": 2,
      "achievementRate": 50,
      "status": "in_progress",
      "nextMission": {
        "missionId": "mission_003",
        "targetPoint": 2000,
        "reward": "영화 보기",
        "remainingPoints": 180
      }
    },
    "missions": [
      {
        "missionId": "mission_001",
        "targetPoint": 500,
        "reward": "간식 데이",
        "achieved": true,
        "achievedAt": "2026-03-20T02:10:00.000Z",
        "createdAt": "2026-03-01T01:00:00.000Z",
        "updatedAt": "2026-03-20T02:10:00.000Z"
      },
      {
        "missionId": "mission_002",
        "targetPoint": 1000,
        "reward": "자율 놀이 시간",
        "achieved": true,
        "achievedAt": "2026-03-25T02:10:00.000Z",
        "createdAt": "2026-03-05T01:00:00.000Z",
        "updatedAt": "2026-03-25T02:10:00.000Z"
      },
      {
        "missionId": "mission_003",
        "targetPoint": 2000,
        "reward": "영화 보기",
        "achieved": false,
        "achievedAt": null,
        "createdAt": "2026-03-10T01:00:00.000Z",
        "updatedAt": null
      }
    ]
  },
  "message": "학급 미션 현황 조회에 성공했습니다."
}
```

---

## 응답 데이터 상세

### 최상위 데이터

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `classId` | string | 클래스 ID |
| `classTotalPoints` | number | 학급 전체 학생의 총 포인트 합계 |
| `missionSummary` | object | 미션 요약 정보 |
| `missions` | array | 미션 목록 |

### `missionSummary`

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `totalMissions` | number | 전체 미션 개수 |
| `achievedMissions` | number | 달성한 미션 개수 |
| `pendingMissions` | number | 남은 미션 개수 |
| `achievementRate` | number | 달성률 (0~100) |
| `status` | string | `empty`, `in_progress`, `completed` |
| `nextMission` | object or null | 다음 목표 미션 정보 |

### `nextMission`

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `missionId` | string | 다음 미션 ID |
| `targetPoint` | number | 목표 포인트 |
| `reward` | string | 달성 보상 설명 |
| `remainingPoints` | number | 다음 목표까지 남은 포인트 |

### `missions` 배열 각 항목

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `missionId` | string | 미션 문서 ID |
| `targetPoint` | number | 목표 포인트 |
| `reward` | string | 달성 보상 |
| `achieved` | boolean | 달성 여부 |
| `achievedAt` | string or null | 달성 시각 |
| `createdAt` | string or null | 생성 시각 |
| `updatedAt` | string or null | 수정 시각 |

---

## 에러 처리

### 에러 응답 형식

```
{
  "success": false,
  "error": {
    "code": "error_code",
    "message": "에러 메시지",
    "details": {}
  }
}
```

### 에러 코드

| 상태 코드 | 에러 코드 | 설명 | 해결 방법 |
| --- | --- | --- | --- |
| 400 | `invalid_class_id` | 클래스 ID가 제공되지 않음 | classId 확인 |
| 401 | `unauthorized` | API 키가 없거나 유효하지 않음 | API 키와 헤더 확인 |
| 403 | `forbidden` | 해당 클래스 접근 권한 없음 | classId 권한 확인 |
| 403 | `insufficient_permissions` | 학급 미션 조회 권한이 없음 | `readClassMissions` 권한 확인 |
| 404 | `class_not_found` | 클래스를 찾을 수 없음 | classId 확인 |
| 429 | `rate_limit_exceeded` | 호출 제한 초과 | 잠시 후 재시도 |
| 500 | `internal_error` | 서버 내부 오류 | 잠시 후 재시도 |

### 에러 응답 예시

```
{
  "success": false,
  "error": {
    "code": "insufficient_permissions",
    "message": "학급 미션 조회 권한이 없습니다.",
    "details": {
      "requiredPermission": "readClassMissions"
    }
  }
}
```

---

## 코드 예제

### cURL

```
curl -X GET \
  "https://growndcard.com/api/v1/classes/NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2/missions" \
  -H "X-API-Key: sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2"
```

### JavaScript (Node.js)

```
const fetch = require('node-fetch');

const API_KEY = 'sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2';
const BASE_URL = 'https://growndcard.com';
const CLASS_ID = 'NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2';

async function getClassMissionStatus() {
  const response = await fetch(
    `${BASE_URL}/api/v1/classes/${CLASS_ID}/missions`,
    {
      method: 'GET',
      headers: {
        'X-API-Key': API_KEY
      }
    }
  );

  const data = await response.json();

  if (!response.ok) {
    throw new Error(data.error?.message || 'API 호출 실패');
  }

  return data.data;
}

getClassMissionStatus()
  .then(result => {
    console.log('학급 총 포인트:', result.classTotalPoints);
    console.log('달성률:', result.missionSummary.achievementRate);
    console.log('다음 미션:', result.missionSummary.nextMission);
  })
  .catch(error => console.error('에러:', error));
```

### Python

```
import requests

API_KEY = 'sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2'
BASE_URL = 'https://growndcard.com'
CLASS_ID = 'NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2'

def get_class_mission_status():
    response = requests.get(
        f'{BASE_URL}/api/v1/classes/{CLASS_ID}/missions',
        headers={
            'X-API-Key': API_KEY
        }
    )

    response.raise_for_status()
    return response.json()['data']

result = get_class_mission_status()
print('학급 총 포인트:', result['classTotalPoints'])
print('미션 달성률:', result['missionSummary']['achievementRate'])
```

---

## 제한 사항

- 교사 계정당 API 키 최대 3개 생성 가능

- 분당 최대 60회, 일일 최대 500회 호출 가능

- API 키는 생성 시 한 번만 표시됨

- 학급 접근 권한이 있는 클래스만 조회 가능

For the site tree, see the [root Markdown](https://slashpage.com/grownd.md).
