# Zellyy API 명세서 이 문서는 Zellyy 프로젝트의 API 엔드포인트와 기능에 대한 상세 명세를 제공합니다. ## 기본 정보 - **기본 URL**: `https://a11.ism.kr/api` - **API 버전**: v1 - **인증 방식**: JWT 토큰 (Bearer Authentication) - **응답 형식**: JSON ## 인증 API ### 회원가입 ``` POST /auth/signup ``` **요청 본문**: ```json { "email": "user@example.com", "password": "securepassword", "username": "username" } ``` **응답 (200 OK)**: ```json { "user": { "id": "uuid", "email": "user@example.com", "username": "username" }, "session": { "access_token": "jwt_token", "refresh_token": "refresh_token", "expires_at": 1672531200 } } ``` ### 로그인 ``` POST /auth/login ``` **요청 본문**: ```json { "email": "user@example.com", "password": "securepassword" } ``` **응답 (200 OK)**: ```json { "user": { "id": "uuid", "email": "user@example.com", "username": "username" }, "session": { "access_token": "jwt_token", "refresh_token": "refresh_token", "expires_at": 1672531200 } } ``` ### 토큰 갱신 ``` POST /auth/refresh ``` **요청 본문**: ```json { "refresh_token": "refresh_token" } ``` **응답 (200 OK)**: ```json { "access_token": "new_jwt_token", "refresh_token": "new_refresh_token", "expires_at": 1672531200 } ``` ### 로그아웃 ``` POST /auth/logout ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **응답 (200 OK)**: ```json { "message": "Successfully logged out" } ``` ## 사용자 API ### 사용자 정보 조회 ``` GET /users/me ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **응답 (200 OK)**: ```json { "id": "uuid", "email": "user@example.com", "username": "username", "display_name": "Display Name", "avatar_url": "https://example.com/avatar.jpg", "is_premium": false, "premium_until": null, "created_at": "2023-01-01T00:00:00Z" } ``` ### 사용자 정보 업데이트 ``` PATCH /users/me ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **요청 본문**: ```json { "display_name": "New Display Name", "avatar_url": "https://example.com/new-avatar.jpg" } ``` **응답 (200 OK)**: ```json { "id": "uuid", "email": "user@example.com", "username": "username", "display_name": "New Display Name", "avatar_url": "https://example.com/new-avatar.jpg", "updated_at": "2023-01-02T00:00:00Z" } ``` ## 카드 API ### 카드 생성 ``` POST /cards ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **요청 본문**: ```json { "content": "This is a card content", "background_color": "#FFFFFF", "text_color": "#000000", "font_family": "system", "font_size": 16, "text_align": "center", "is_public": false, "tags": ["personal", "ideas"] } ``` **응답 (201 Created)**: ```json { "id": "uuid", "content": "This is a card content", "background_color": "#FFFFFF", "text_color": "#000000", "font_family": "system", "font_size": 16, "text_align": "center", "is_public": false, "is_synced": false, "created_at": "2023-01-01T00:00:00Z", "updated_at": "2023-01-01T00:00:00Z", "tags": ["personal", "ideas"] } ``` ### 카드 목록 조회 ``` GET /cards ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **쿼리 파라미터**: - `page`: 페이지 번호 (기본값: 1) - `limit`: 페이지당 항목 수 (기본값: 20, 최대: 100) - `sort`: 정렬 기준 (options: created_at, updated_at, 기본값: created_at) - `order`: 정렬 순서 (options: asc, desc, 기본값: desc) - `tag`: 태그로 필터링 (선택 사항) - `search`: 내용 검색 (선택 사항) **응답 (200 OK)**: ```json { "data": [ { "id": "uuid1", "content": "Card 1 content", "background_color": "#FFFFFF", "text_color": "#000000", "font_family": "system", "font_size": 16, "text_align": "center", "is_public": false, "is_synced": false, "created_at": "2023-01-01T00:00:00Z", "updated_at": "2023-01-01T00:00:00Z", "tags": ["personal"] }, { "id": "uuid2", "content": "Card 2 content", "background_color": "#F0F0F0", "text_color": "#333333", "font_family": "arial", "font_size": 18, "text_align": "left", "is_public": true, "is_synced": true, "created_at": "2023-01-02T00:00:00Z", "updated_at": "2023-01-02T00:00:00Z", "tags": ["ideas", "public"] } ], "pagination": { "total": 42, "page": 1, "limit": 20, "total_pages": 3 } } ``` ### 카드 상세 조회 ``` GET /cards/{card_id} ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **응답 (200 OK)**: ```json { "id": "uuid", "content": "This is a card content", "background_color": "#FFFFFF", "text_color": "#000000", "font_family": "system", "font_size": 16, "text_align": "center", "is_public": false, "is_synced": false, "created_at": "2023-01-01T00:00:00Z", "updated_at": "2023-01-01T00:00:00Z", "tags": ["personal", "ideas"], "share_count": 2, "share_platforms": ["facebook", "instagram"] } ``` ### 카드 업데이트 ``` PATCH /cards/{card_id} ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **요청 본문**: ```json { "content": "Updated card content", "background_color": "#F0F0F0", "is_public": true, "tags": ["personal", "ideas", "updated"] } ``` **응답 (200 OK)**: ```json { "id": "uuid", "content": "Updated card content", "background_color": "#F0F0F0", "text_color": "#000000", "font_family": "system", "font_size": 16, "text_align": "center", "is_public": true, "is_synced": false, "created_at": "2023-01-01T00:00:00Z", "updated_at": "2023-01-02T00:00:00Z", "tags": ["personal", "ideas", "updated"] } ``` ### 카드 삭제 ``` DELETE /cards/{card_id} ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **응답 (204 No Content)** ## 소셜 공유 API ### 소셜 계정 연동 ``` POST /social/connect/{platform} ``` **지원 플랫폼**: `facebook`, `instagram`, `twitter` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **요청 본문**: ```json { "access_token": "platform_access_token", "refresh_token": "platform_refresh_token", "expires_at": 1672531200 } ``` **응답 (200 OK)**: ```json { "platform": "facebook", "connected": true, "platform_user_id": "platform_user_id", "expires_at": 1672531200 } ``` ### 소셜 계정 연동 해제 ``` DELETE /social/connect/{platform} ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **응답 (204 No Content)** ### 연동된 소셜 계정 목록 ``` GET /social/accounts ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **응답 (200 OK)**: ```json { "accounts": [ { "platform": "facebook", "platform_user_id": "facebook_user_id", "connected_at": "2023-01-01T00:00:00Z", "expires_at": 1672531200 }, { "platform": "instagram", "platform_user_id": "instagram_user_id", "connected_at": "2023-01-02T00:00:00Z", "expires_at": 1672617600 } ] } ``` ### 카드 소셜 공유 ``` POST /cards/{card_id}/share/{platform} ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **요청 본문**: ```json { "message": "Check out my new card!" // 선택적 메시지 } ``` **응답 (200 OK)**: ```json { "id": "share_id", "card_id": "card_id", "platform": "facebook", "status": "success", "share_url": "https://facebook.com/post/123456", "shared_at": "2023-01-01T00:00:00Z" } ``` ## 구독 API ### 구독 플랜 목록 ``` GET /subscriptions/plans ``` **응답 (200 OK)**: ```json { "plans": [ { "id": "monthly", "name": "Monthly Premium", "description": "Monthly subscription with cloud sync", "price": 4.99, "currency": "USD", "interval": "month", "features": [ "Cloud sync", "Unlimited cards", "Premium templates" ] }, { "id": "yearly", "name": "Yearly Premium", "description": "Yearly subscription with cloud sync (save 20%)", "price": 47.99, "currency": "USD", "interval": "year", "features": [ "Cloud sync", "Unlimited cards", "Premium templates", "Priority support" ] } ] } ``` ### 구독 생성 ``` POST /subscriptions ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **요청 본문**: ```json { "plan_id": "monthly", "payment_method_id": "payment_method_id", "payment_provider": "stripe" } ``` **응답 (201 Created)**: ```json { "id": "subscription_id", "plan_id": "monthly", "status": "active", "start_date": "2023-01-01T00:00:00Z", "end_date": "2023-02-01T00:00:00Z", "payment_provider": "stripe", "payment_id": "payment_id" } ``` ### 현재 구독 정보 ``` GET /subscriptions/current ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **응답 (200 OK)**: ```json { "id": "subscription_id", "plan_id": "monthly", "status": "active", "start_date": "2023-01-01T00:00:00Z", "end_date": "2023-02-01T00:00:00Z", "auto_renew": true, "payment_provider": "stripe", "payment_id": "payment_id" } ``` ### 구독 취소 ``` POST /subscriptions/cancel ``` **요청 헤더**: ``` Authorization: Bearer jwt_token ``` **응답 (200 OK)**: ```json { "id": "subscription_id", "status": "canceled", "end_date": "2023-02-01T00:00:00Z", "message": "Subscription will be active until the end date" } ``` ## 오류 응답 모든 API 엔드포인트는 오류 발생 시 다음과 같은 형식으로 응답합니다: **응답 (4xx/5xx)**: ```json { "error": { "code": "error_code", "message": "Error message description", "details": {} // 추가 오류 정보 (선택 사항) } } ``` ### 공통 오류 코드 - `invalid_request`: 잘못된 요청 형식 - `authentication_required`: 인증 필요 - `invalid_credentials`: 잘못된 인증 정보 - `permission_denied`: 권한 없음 - `resource_not_found`: 리소스를 찾을 수 없음 - `rate_limit_exceeded`: 요청 한도 초과 - `internal_server_error`: 서버 내부 오류 ## 웹훅 (Webhook) Zellyy는 다음 이벤트에 대한 웹훅을 제공합니다: ### 웹훅 등록 ``` POST /webhooks ``` **요청 헤더**: ``` Authorization: Bearer admin_token ``` **요청 본문**: ```json { "url": "https://your-service.com/webhook", "events": ["user.created", "subscription.created", "subscription.canceled"], "secret": "your_webhook_secret" } ``` **응답 (201 Created)**: ```json { "id": "webhook_id", "url": "https://your-service.com/webhook", "events": ["user.created", "subscription.created", "subscription.canceled"], "created_at": "2023-01-01T00:00:00Z" } ``` ### 웹훅 이벤트 형식 ```json { "id": "event_id", "type": "event.type", "created_at": "2023-01-01T00:00:00Z", "data": { // 이벤트 관련 데이터 } } ``` ## 결론 이 API 명세서는 Zellyy 프로젝트의 기본 기능을 구현하기 위한 엔드포인트를 정의합니다. 프로젝트가 발전함에 따라 추가 엔드포인트와 기능이 확장될 수 있습니다.