YWS 문서
YWS 콘솔로 이동
앱 연동/API (JSON)

API (JSON)

스크립트·CLI·자동화 도구에서 YWS를 다루는 JSON API입니다. 주소는 https://jimmy-home.com/api/v1이고, 응답과 요청 본문은 모두 JSON입니다. 앞으로 만들 MCP 서버, IaC(plan/apply), CLI도 이 API를 씁니다.

콘솔과 같은 규칙: API와 콘솔 버튼은 같은 코드(app/services/)를 부릅니다. 이름 규칙, 한도, 소유자·공유 권한이 콘솔과 똑같습니다. 콘솔에서 안 되는 일은 API로도 안 되고, 그 반대도 마찬가지입니다.

토큰 만들기

콘솔 상단 연동 → API 토큰(/dashboard/api-tokens) → 이름, 만료(30일/90일/1년/없음), 권한 선택 → 토큰 만들기. 토큰(yws_pat_...)은 그때 한 번만 보여 주니 바로 복사하세요. 잃어버렸거나 유출됐으면 폐기하고 새로 만듭니다.

권한 할 수 있는 것
읽기 (항상 포함) 목록, 상태, 설정 조회 (GET)
쓰기 만들기, 시작·정지, 사양·코드 변경, 저장소 연결, 공유, Lambda 실행, DB 비밀번호 재발급
삭제 EC2·저장소·Lambda·DB 삭제 (되돌릴 수 없음)
  • 토큰은 만든 사람의 권한으로만 동작합니다. 관리자의 토큰이라도 관리자 권한은 없습니다: 남의 EC2를 켜고 끄는 일 등은 콘솔에서만 할 수 있습니다.
  • 포털에는 토큰의 해시만 저장되고, 목록에는 앞 몇 글자만 표시됩니다.
  • 사용자당 토큰은 최대 20개입니다.
export YWS_TOKEN=yws_pat_...
curl -H "Authorization: Bearer $YWS_TOKEN" https://jimmy-home.com/api/v1/ec2
curl -H "Authorization: Bearer $YWS_TOKEN" -H "Content-Type: application/json" \
     -d '{"name": "my-vol", "size_gb": 10}' https://jimmy-home.com/api/v1/storage
import requests
api = requests.Session()
api.headers["Authorization"] = "Bearer yws_pat_..."
for e in api.get("https://jimmy-home.com/api/v1/ec2").json()["items"]:
    print(e["name"], e["status"], e["state"] and e["state"]["label"])
  • /api/ 경로는 Cloudflare 브라우저 무결성 검사에서 예외라서 어떤 HTTP 클라이언트(Python 표준 urllib 포함)로도 부를 수 있습니다. 콘솔 페이지는 여전히 검사 대상입니다.
  • 브라우저에서 로그인한 상태라면 토큰 없이 세션으로도 부를 수 있습니다(권한 전체). 단, 변경 요청은 Content-Type: application/json이어야 합니다(다른 사이트가 사용자 몰래 요청을 보내는 CSRF 방지).

엔드포인트

{id}는 목록에 나오는 id입니다. 목록(/ec2, /storage, /lambdas, /databases, /networks, /loadbalancers)은 ?name=이름으로 하나만 찾을 수 있습니다.

  • GET /me: 나, 인증 방식, 권한

EC2

메서드 경로 권한 설명
GET /ec2 읽기 내 EC2 + 공유받은 EC2 (access: owner/shared)
GET /ec2/{id} 읽기 하나. state는 실시간 상태(running, stopped, error:...)
POST /ec2 쓰기 {name, cpu, memory_gb, disk_gb, ssh_key_id?, gpu?, node_id?}. ssh_key_id가 없으면 새 키를 만들고 개인키를 private_key로 한 번만 돌려줌
PATCH /ec2/{id} 쓰기 {cpu, memory_gb} 사양 변경 (주인만, 켜져 있으면 재시작)
POST /ec2/{id}/start, /ec2/{id}/stop 쓰기 시작·정지 (주인, 공유받은 사람)
GET /ec2/{id}/history 읽기 누가 언제 켜고 껐는지
POST /ec2/{id}/shares 쓰기 {username} 공유 (주인만)
DELETE /ec2/{id}/shares/{share_id} 쓰기 공유 해제
DELETE /ec2/{id} 삭제 삭제 (주인만)
POST /ec2/{id}/inbound 쓰기 {domain_id, port} 내 도메인 → 이 EC2의 포트 (22 불가). 응답에 url
DELETE /ec2/{id}/inbound/{rule_id} 쓰기 인바운드 규칙 삭제
PUT /ec2/{id}/internet-outbound 쓰기 {allowed: true|false} 인터넷으로 나가는 연결 허용

POST /ec2는 생성을 시작만 하고 돌려줍니다. GET /ec2/{id}의 state.state가 running이 될 때까지 몇 초 간격으로 조회하세요.

저장소

메서드 경로 권한 설명
GET /storage, /storage/{id} 읽기 내 것 + 공유받은 것. attachments(공유받은 경우 내 연결만)
POST /storage 쓰기 {name, size_gb} (size_gb: 10, 20, 50, 100, 200, 500)
POST /storage/{id}/attachments 쓰기 {target_id} 내 EC2/Lambda에 연결 → /mnt/저장소이름 (EC2는 재시작)
DELETE /storage/{id}/attachments/{attachment_id} 쓰기 연결 해제
POST / DELETE /storage/{id}/shares[/{share_id}] 쓰기 공유 / 해제 (해제하면 그 사람의 연결도 끊김)
DELETE /storage/{id} 삭제 연결이 남아 있으면 409

Lambda

메서드 경로 권한 설명
GET /lambdas, /lambdas/{id} 읽기 하나 조회 시 code 포함
POST /lambdas 쓰기 {name, runtime: python|node|cpp, memory_mi?, cpu_milli?, code?}
PATCH /lambdas/{id} 쓰기 {code?, runtime?} (실행 중인 인스턴스는 재시작)
POST /lambdas/{id}/invoke 쓰기 {event?} → 함수 응답 {statusCode, headers, body} (콜드 스타트면 몇 초 걸림)
DELETE /lambdas/{id} 삭제
POST / DELETE /lambdas/{id}/inbound[/{rule_id}] 쓰기 URL 트리거: {domain_id, port} → https://도메인으로 오는 요청이 이 함수를 실행
PUT /lambdas/{id}/internet-outbound 쓰기 {allowed}
PUT /lambdas/{id}/schedule 쓰기 예약 실행: {mode: "cron", cron: "0 9 * * *"} / {mode: "once", run_once_at: "2026-10-06T09:00"} / {mode: "off"} (한국 시간)
GET / POST /lambdas/{id}/mail-triggers 읽기 / 쓰기 메일 트리거 목록 / {tag, keep_in_mailbox?} → address(나+태그@...)로 오는 메일이 실행
PATCH / DELETE /lambdas/{id}/mail-triggers/{trigger_id} 쓰기 {enabled} 켜기·끄기 / 삭제

DB

메서드 경로 권한 설명
GET /databases, /databases/{id} 읽기 접속 주소(host, port, user, url_template). 비밀번호는 없음
POST /databases 쓰기 {name, engine: postgres|mysql|redis} → 응답에 password 한 번만
POST /databases/{id}/reset-password 쓰기 새 password
DELETE /databases/{id} 삭제

네트워크 캔버스 · 로드밸런서

메서드 경로 권한 설명
GET /networks, /networks/{id} 읽기 노드(kind: ec2/lambda/database/loadbalancer, 인바운드 규칙, LB 멤버)와 연결(from/to 이름, 포트, 방향)
POST /networks 쓰기 {name} 빈 캔버스
DELETE /networks/{id} 삭제 캔버스와 연결 정책, 그 위의 로드밸런서 삭제 (EC2·Lambda·DB는 그대로)
POST /networks/{id}/nodes 쓰기 {resource_id, x?, y?} 내 EC2·Lambda·DB 올리기
PATCH / DELETE /networks/{id}/nodes/{node_id} 쓰기 {x, y} 위치 / 캔버스에서 내리기 (연결도 같이 삭제, LB 노드면 LB 삭제)
POST /networks/{id}/edges 쓰기 {from_node_id, to_node_id, port_mode?: all_except_22|custom, port_ranges?: "80,443,8000-8100", direction?: uni|bi}. 같은 쌍에 다시 보내면 수정. DB로의 연결은 EC2에서만, 그 DB 서버 포트만 → 응답 message에 접속 정보 파일 위치
DELETE /networks/{id}/edges/{edge_id} 쓰기 연결 삭제
POST /networks/{id}/edges/{edge_id}/env 쓰기 EC2 → DB 연결의 접속 정보 파일 다시 쓰기
POST /networks/{id}/loadbalancers 쓰기 {name, x?, y?} 로드밸런서 만들기 (응답의 resource_id가 LB id)
POST / DELETE /networks/{id}/loadbalancers/{lb_id}/members[/{ec2_id}] 쓰기 {ec2_id} 멤버 추가 / 제거
GET /loadbalancers 읽기 멤버와 인바운드 규칙
POST / DELETE /loadbalancers/{id}/inbound[/{rule_id}] 쓰기 {domain_id, port} → 멤버들로 분산
PUT /loadbalancers/{id}/internet-outbound 쓰기 {allowed} 모든 멤버에 적용

SSH 키 · 도메인

메서드 경로 권한 설명
GET /ssh-keys 읽기 EC2 만들 때 쓸 ssh_key_id, 사용 중인 EC2
POST /ssh-keys 쓰기 {name, public_key} 공개키 등록 (ssh-ed25519 ...)
DELETE /ssh-keys/{id} 삭제 사용 중이면 409
GET /domains 읽기 내 도메인과 연결된 EC2·Lambda·LB와 포트
POST /domains 쓰기 {subdomain} → subdomain.jimmy-home.com (예약어·중복 불가)
DELETE /domains/{id} 삭제 인바운드 규칙에 쓰이고 있으면 409

오류

항상 같은 모양입니다. 검증 오류가 여러 개면 messages에 전부 담깁니다.

{"error": "invalid", "message": "용량 값이 올바르지 않습니다."}
HTTP error 뜻
400 invalid 입력값 오류 (이름 규칙, 범위, JSON 아님 등)
401 unauthorized 토큰 없음·만료·폐기
403 insufficient_scope / forbidden 토큰에 그 권한이 없음 / 승인 안 된 사용자, 세션 요청에 JSON 아님
404 not_found 없거나 내 것이 아님 (남의 리소스도 "없음"으로 응답)
409 conflict 이미 있는 이름, 이미 정지됨, 아직 연결돼 있음 등
502 upstream_error 클러스터(k8s·DB 서버) 쪽 실패. 잠시 후 다시 시도

구조

  • app/services/: 검증·권한·k8s 호출·정리 순서 (ec2.py, storage.py, lambdas.py, databases.py, resources.py(삭제)). 콘솔 라우트와 API가 같은 함수를 부르고, 실패는 ServiceError(코드·HTTP 상태·한국어 메시지)로 올라옴
  • app/routers/api.py: /api/v1 라우트, 인증(Bearer 토큰 또는 세션), 응답 모양
  • app/routers/api_tokens.py + 모델 ApiToken: 토큰 발급·폐기 (SHA-256 해시만 저장)
  • 버전 고정: 응답 필드를 없애거나 의미를 바꾸는 변경은 /api/v2로. 필드 추가는 v1에서 함
  • app/services/의 각 모듈: ec2, storage, lambdas(트리거 포함), databases, network(캔버스·로드밸런서·연결), inbound(인바운드 규칙·인터넷 아웃바운드), keys, domains, resources(삭제)
  • 아직 없는 것: OAuth 액세스 토큰으로 API 호출(scope 동의 화면, MCP 작업 때 함께), Pages·메일, 목록 페이지 나누기(지금은 전부 한 번에)