Sign In

🐣 그라운드 포인트 API 사용 가이드

👉🏻 그라운드에서 학생에게 포인트를 부여하는 포인트 API 기능을 설명합니다.

목차

시작하기

그라운드 포인트 API를 사용하면 외부 애플리케이션에서 학생들에게 포인트를 부여할 수 있습니다. 퀴즈 앱, 게임, 출석 체크 시스템 등 다양한 서비스와 연동이 가능합니다.

기본 정보

프로토콜: HTTPS
인증 방식: API Key (Header)

API 키 발급

1. 그라운드에 로그인

교사 계정으로 그라운드에 로그인합니다.

2. 내 정보 페이지 이동

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

3. API 키 관리 탭

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

4. 새 API 키 생성

1.
"새 API 키 생성" 버튼 클릭
2.
다음 정보 입력:
API 키 이름: 애플리케이션 이름 (예: "출석체크 앱")
만료 기간: 선택 (무제한 또는 30일/90일/180일/1년)
권한 설정: 포인트 부여 권한 선택
호출 제한: 기본값(분당 60회, 일일 500회)
3.
"API 키 생성" 클릭

5. API 키 저장

⚠️ 중요: API 키는 한 번만 표시됩니다!
sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o123
반드시 안전한 곳에 복사하여 보관하세요.

제한 사항

교사 계정당 최대 3개의 API 키 생성 가능
일일 최대 500회 호출 제한

인증 방식

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

포인트 부여 API

엔드포인트

POST /api/v1/classes/{classId}/students/{studentCode}/points
클래스 id 확인 : 클래스별로 다른 클래스 id가 부여됩니다. → [클래스 정보] 메뉴에서 확인

URL 파라미터

파라미터
타입
설명
예시
classId
string
클래스 ID (그라운드에서 확인)
NP0hetJ3wyQKFtRnFeftmPiy8Dl7_2
studentCode
number
학생 번호 (출석번호)
2
💡 classId 확인 방법: 그라운드 → 클래스 관리 → 클래스 카드에서 "ID" 확인

요청 헤더

헤더
필수
Content-Type
application/json
X-API-Key
발급받은 API 키

요청 본문 (JSON)

필드
타입
필수
설명
예시
type
string
포인트 종류
"reward(+포인트)" 또는 "penalty(-포인트)"
points
number
포인트 값 (0.01~1000)
10.5
description
string
포인트 설명 (1~500자)
"퀴즈 정답"

요청 예시

{ "type": "reward", "points": 10, "description": "타이핑 게임 클리어" } }

성공 응답 (200 OK)

{ "success": true, "data": { "recordId": "rec_xyz789", "studentId": "stu_abc123", "studentCode": 2, "type": "reward", "pointsAwarded": 10, "bonusApplied": 0, "totalPoints": 150.5, "currentLevel": 5, "leveledUp": false, "createdAt": "2025-11-12T01:23:45.000Z" }, "message": "포인트가 성공적으로 반영되었습니다." }

응답 필드 설명

필드
타입
설명
recordId
string
포인트 기록 ID
studentId
string
학생의 내부 ID
studentCode
number
학생 번호
type
string
포인트 종류
pointsAwarded
number
실제 부여된 포인트
bonusApplied
number
적용된 보너스 배율 (0이면 보너스 없음)
totalPoints
number
부여 후 학생의 총 포인트
currentLevel
number
학생의 현재 레벨
leveledUp
boolean
레벨업 여부
createdAt
string
포인트 부여 시각 (ISO 8601)

에러 처리

에러 응답 형식

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

에러 코드

상태 코드
에러 코드
설명
해결 방법
400
invalid_type
type이 올바르지 않음
"reward" 또는 "penalty" 사용
400
invalid_points
points 값이 범위를 벗어남
0.01~1000 사이 값 사용
400
invalid_description
description이 비어있거나 너무 김
1~500자 사이 문자열 사용
400
invalid_student_code
학생 번호가 제공되지 않음
studentCode 확인
401
unauthorized
API 키가 없거나 유효하지 않음
API 키 확인, X-API-Key 헤더 확인
403
forbidden
해당 클래스 접근 권한 없음
classId 확인
404
student_not_found
학생을 찾을 수 없음
studentCode 확인
429
rate_limit_exceeded
호출 제한 초과
잠시 후 재시도
500
internal_error
서버 내부 오류
잠시 후 재시도, 반복되면 문의

에러 응답 예시

{ "success": false, "error": { "code": "student_not_found", "message": "해당 학생 번호에 해당하는 학생을 찾을 수 없습니다.", "details": { "classId": "NP0hetJ3wyQKFtRnFeftmPiy8Dl3_2", "studentCode": 99 } } }

코드 예제

cURL

curl -X POST \ "https://growndcard.com/api/v1/classes/NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2/students/2/points" \ -H "Content-Type: application/json" \ -H "X-API-Key: sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5123" \ -d '{ "type": "reward", "points": 10, "description": "퀴즈 정답" }'

JavaScript (Node.js)

const fetch = require('node-fetch'); const API_KEY = 'sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p2'; const BASE_URL = 'https://growndcard.com'; const CLASS_ID = 'NP0hetJ3wyQKFtRnFeftmPiy8Dl3_2'; async function awardPoints(studentCode, points, description) { try { const response = await fetch( `${BASE_URL}/api/v1/classes/${CLASS_ID}/students/${studentCode}/points`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY }, body: JSON.stringify({ type: 'reward', points: points, description: description }) } ); const data = await response.json(); if (!response.ok) { throw new Error(`API Error: ${data.error.message}`); } console.log('포인트 부여 성공:', data.data); return data.data; } catch (error) { console.error('포인트 부여 실패:', error.message); throw error; } } // 사용 예시 awardPoints(2, 10, '타이핑 게임 클리어') .then(result => console.log('결과:', result)) .catch(error => console.error('에러:', error));

Python

import requests import json API_KEY = 'sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6' BASE_URL = 'https://growndcard.com' CLASS_ID = 'NP0hetJ3wyQKFtRnFeftmPiy8Dl2_2' def award_points(student_code, points, description): """학생에게 포인트 부여""" url = f'{BASE_URL}/api/v1/classes/{CLASS_ID}/students/{student_code}/points' headers = { 'Content-Type': 'application/json', 'X-API-Key': API_KEY } payload = { 'type': 'reward', 'points': points, 'description': description } try: response = requests.post(url, headers=headers, json=payload) response.raise_for_status() data = response.json() print(f"포인트 부여 성공: {data['data']}") return data['data'] except requests.exceptions.HTTPError as e: error_data = response.json() print(f"API 에러: {error_data['error']['message']}") raise except Exception as e: print(f"요청 실패: {str(e)}") raise # 사용 예시 if __name__ == '__main__': result = award_points(2, 10, '퀴즈 정답') print(f"총 포인트: {result['totalPoints']}")

TypeScript (React/Next.js)

interface AwardPointsRequest { type: 'reward' | 'penalty'; points: number; description: string; source?: string; metadata?: Record<string, any>; } interface AwardPointsResponse { success: boolean; data?: { recordId: string; studentCode: number; pointsAwarded: number; totalPoints: number; currentLevel: number; leveledUp: boolean; createdAt: string; }; message?: string; } class GroundApiClient { private apiKey: string; private baseUrl: string; private classId: string; constructor(apiKey: string, classId: string) { this.apiKey = apiKey; this.classId = classId; this.baseUrl = 'https://growndcard.com'; } async awardPoints( studentCode: number, request: AwardPointsRequest ): Promise<AwardPointsResponse> { const url = `${this.baseUrl}/api/v1/classes/${this.classId}/students/${studentCode}/points`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': this.apiKey }, body: JSON.stringify(request) }); const data = await response.json(); if (!response.ok) { throw new Error(data.error?.message || 'API 호출 실패'); } return data; } } // 사용 예시 const client = new GroundApiClient( 'sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p3', 'NP0hetJ3wyQKFtRnFeftmPiy8Dl3_2' ); async function example() { try { const result = await client.awardPoints(2, { type: 'reward', points: 10, description: '타이핑 게임 클리어' }); console.log('포인트 부여 성공:', result.data); } catch (error) { console.error('포인트 부여 실패:', error); } }

PHP

<?php function awardPoints($studentCode, $points, $description) { $apiKey = 'sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p1'; $classId = 'NP0hetJ3wyQKFtRnFeftmPiy8Dl3_2'; $baseUrl = 'https://growndcard.com'; $url = "{$baseUrl}/api/v1/classes/{$classId}/students/{$studentCode}/points"; $data = [ 'type' => 'reward', 'points' => $points, 'description' => $description ]; $options = [ 'http' => [ 'method' => 'POST', 'header' => [ 'Content-Type: application/json', "X-API-Key: {$apiKey}" ], 'content' => json_encode($data) ] ]; $context = stream_context_create($options); $response = file_get_contents($url, false, $context); if ($response === false) { throw new Exception('API 호출 실패'); } $result = json_decode($response, true); if (!$result['success']) { throw new Exception($result['error']['message']); } return $result['data']; } // 사용 예시 try { $result = awardPoints(2, 10, '퀴즈 정답'); echo "포인트 부여 성공: 총 포인트 = {$result['totalPoints']}\n"; } catch (Exception $e) { echo "에러: " . $e->getMessage() . "\n"; }

제한 사항

API 키 제한

교사 계정당 최대 3개 API 키 생성 가능
API 키는 생성 시 한 번만 표시됨 (분실 시 재발급 필요)

호출 제한 (Rate Limit)

분당 최대: 60회
일일 최대: 500회
제한 초과 시 429 Too Many Requests 응답

포인트 제한

한 번에 부여 가능한 포인트: 0.01 ~ 1000점
설명(description): 1 ~ 500자

보안 권장사항

1.
⚠️ API 키를 절대 공개 저장소에 커밋하지 마세요
2.
✅ 환경 변수(.env)에 저장하세요
3.
✅ 프론트엔드에 노출하지 말고 백엔드에서만 사용하세요
4.
✅ 정기적으로 API 키를 재발급하세요

FAQ

Q1. classId는 어디서 확인하나요?

A: 그라운드 → 클래스 관리 → 각 클래스 카드의 "ID" 필드에서 확인할 수 있습니다.

Q2. 학생 번호(studentCode)는 무엇인가요?

A: 학생의 출석번호입니다. 그라운드의 학생 목록에서 확인할 수 있습니다.

Q3. API 키를 분실했어요!

A: API 키는 재조회가 불가능합니다. 기존 키를 삭제하고 새로운 키를 발급받으세요.

Q4. 감점 포인트(penalty) 타입은 어떻게 작동하나요?

A: api 호출시 type: "penalty"로 설정하면 학생의 포인트가 감소합니다.

Q6. 일일 호출 제한을 늘릴 수 있나요?

A: 현재는 최대 500회로 고정되어 있습니다. 더 많은 호출이 필요한 경우 문의 게시판으로 연락주세요.

지원

문의

문의 게시판: 그라운드 → 문의 게시판

버그 리포트

API 사용 중 문제가 발생하면:
1.
에러 메시지 전체
2.
요청 URL 및 본문
3.
API 키 ID (키 전체가 아닌 ID만)
위 정보와 함께 문의 게시판에 제보해 주세요.
마지막 업데이트: 2025년 11월 12일
API 버전: v1