API 레퍼런스
endue OS API v0.3.0 — Station·기기·앱·명령·화면·이벤트·크레딧을 다루는 공개 REST API 예요. 사람이 쓰는 데스크톱도, 서버·CI 도, AI 에이전트도 같은 API 를 불러요. 아래 표의 오퍼레이션 266개가 전부이고, 이 쪽은 계약(OpenAPI 3.1)에서 매 빌드 다시 만들어요.
시작하기
https://dev.api.endueos.com개발 환경http://127.0.0.1:8900로컬 스택 — local/up.shhttps://api.endueos.com운영 — 예정, 아직 열지 않았다/api/v1 아래에 있어요.Authorization: Bearer <JWT>endue 계정 — endue AI 와 같은 계정Authorization: Bearer osk_…Station API 키 (또는 X-API-Key)첫 호출 — 내 Station 목록:
curl -s http://127.0.0.1:8900/api/v1/stations \ -H "Authorization: Bearer $TOKEN"
# 200{ "data": [{ "station_id": "stn_01J9ZK3Q8M4XW7D2N5R6T0V1BC", "name": "lab", … }], "meta": { "request_id": "…", "timestamp": "2026-10-05T01:02:03Z", "pagination": { "page": 1, "limit": 20, "total": 1, "has_next_page": false } }}공통 규칙
모든 오퍼레이션에 같이 적용돼요. 오퍼레이션 쪽에서는 다시 적지 않아요.
| 무엇 | 규칙 |
|---|---|
| 성공 응답 | { data, meta }. meta.request_id·timestamp, 목록이면 meta.pagination(page·limit·total·has_next_page) |
| 오류 응답 | { error: { code, message, details, suggest }, meta }. code 로 분기해요 — 오류 코드 |
| 요청 추적 | 모든 응답에 X-Request-Id 헤더 — 문의할 때 이 값을 알려 주세요 |
| 목록 | ?page=1&limit=20 — limit 최대 200 |
| 권한 | 소유자만. 남의 것은 403 이 아니라 404 — 있는지조차 알리지 않아요. API 키는 자기 Station 안에서만 |
| 오래 걸리는 일 | 명령은 wait_ms(기본 25초) 안에 끝나면 201, 아니면 202 + Location — 명령 |
| 다시 보내기 | 명령의 request_id 는 멱등 키 — 24시간 안에 같은 키·같은 입력이면 같은 명령 |
| 한도 | 429 RATE_LIMITED 면 Retry-After 초 뒤에 |
| id·시각 | id 는 접두사 + ULID (stn_·app_·res_·cmd_ …), 시각은 RFC 3339 UTC |
| 비밀값 | API 키·연결 토큰·웹훅 비밀은 만들 때 응답에서 한 번만 보여요 |
{ "error": { "code": "RESOURCE_OFFLINE", "message": "Resource is offline", "details": {}, "suggest": null }, "meta": { "request_id": "…", "timestamp": "2026-10-05T01:02:03Z" }}오퍼레이션
묶음마다 하는 일 순서로 놓았어요. 줄을 누르면 파라미터·본문·응답·예시가 있는 쪽으로 가요.
Station
사용자의 환경 — 컴퓨터 한 대처럼. 만들기·조회·한눈에 보기·사용량.
OS
Station 에 하나인 OS — 설정·한도, 멈추기(halt)와 켜기(boot).
기기
내 기기에 설치한 것(actual)과 클라우드에 만든 것(virtual). 만들기·조회·시작·정지, 에이전트·도구·화면·명령.
/stations/{station_id}/devicesPOST기기 만들기·연결/stations/{station_id}/devicesGET클라우드에 만들 수 있는 kind/stations/{station_id}/device-kindsGET기기 조회/devices/{device_id}PATCH기기 수정/devices/{device_id}DELETE기기 지우기/devices/{device_id}POST기기 시작 (virtual)/devices/{device_id}/startPOST기기 정지 (virtual)/devices/{device_id}/stopPOST기기 재시작 (virtual)/devices/{device_id}/restartPOST기기 켜기/devices/{device_id}/enablePOST기기 끄기/devices/{device_id}/disableGET에이전트 조회/devices/{device_id}/agentPOST연결 토큰 회전/devices/{device_id}/agent/rotate-tokenGET도구 카탈로그/devices/{device_id}/toolsGET기기의 명령 기록/devices/{device_id}/commandsPOST명령 보내기/devices/{device_id}/commandsGET화면 한 장/devices/{device_id}/screenGET설치된 앱 목록/devices/{device_id}/installed-appsWorkspace 앱
CLI-Anything 앱 카탈로그·설치·SKILL·실행.
로컬 에이전트
OpenCode·Claude Code·OpenClaw·Hermes의 설치·세션·작업·취소.
/stations/{station_id}/local-agentsGET에이전트 세션 목록/workspaces/{workspace_id}/agent-sessionsPOST에이전트 세션 시작/workspaces/{workspace_id}/agent-sessionsGET세션과 실행 결과/workspaces/{workspace_id}/agent-sessions/{session_id}POST에이전트 작업 취소/workspaces/{workspace_id}/agent-sessions/{session_id}/cancelPOST에이전트 세션 종료/workspaces/{workspace_id}/agent-sessions/{session_id}/closePOST에이전트에 작업 맡기기/workspaces/{workspace_id}/agent-sessions/{session_id}/promptsGET설치한 로컬 에이전트/workspaces/{workspace_id}/local-agentsPOST로컬 에이전트 설치/workspaces/{workspace_id}/local-agents기기 안의 앱
기기 안의 앱을 저장하고 Dock 에 고정·실행하기.
명령
명령 조회·롱폴·취소·출력·블롭과 Station 의 명령 기록. 보내기는 기기 묶음의 POST /devices/{id}/commands.
/commands/{command_id}POST명령 취소/commands/{command_id}/cancelGET명령 출력 받기/commands/{command_id}/outputGET명령 블롭 받기/commands/{command_id}/blobs/{name}GETStation 의 명령 기록/stations/{station_id}/commandsGET리소스의 명령 기록 (옛 경로)/resources/{resource_id}/commandsPOST명령 보내기 (옛 경로)/resources/{resource_id}/commandsDock
Dock 1단의 순서 — 기기와 앱. 읽기와 통째로 바꾸기.
이벤트
Station 이벤트 — 입장권, SSE, WebSocket.
웹훅
서명된 이벤트 전달 — 만들기·목록·다시 켜기.
저장 객체
Station 의 파일 저장소 (R2).
API 키
서버·CI 용 Station API 키(osk_). 만들기·목록·폐기.
내 계정
로그인한 사용자 — 계정과 크레딧 잔액.
프로젝트
Station 을 묶는 단위 — 사용자가 만들고, 프로젝트의 Station·키·감사 로그를 본다.
크레딧
계정의 크레딧 지갑·원장·단가·충전. 결제는 v0.2.0 에서 테스트(mock)만 된다.
/billing/walletGET크레딧 원장/billing/ledgerGET사용량 요약 (크레딧)/billing/usageGET단가표/billing/ratesGET크레딧 상품/billing/packagesPOST충전 시작 (체크아웃)/billing/checkoutsGET체크아웃 조회/billing/checkouts/{checkout_id}POST체크아웃 확인 (테스트 결제)/billing/checkouts/{checkout_id}/confirmPOST체크아웃 취소/billing/checkouts/{checkout_id}/cancelPOST결제 웹훅 (예정)/billing/webhooks/{provider}GETgetPurchaseOptions/billing/purchase-optionsPOSTcreateOrgCheckout/orgs/{org_id}/billing/checkoutsGETlistOrgLedgerEntries/orgs/{org_id}/billing/ledgerGETgetOrgUsageSummary/orgs/{org_id}/billing/usageGETgetOrgWallet/orgs/{org_id}/billing/wallet모니터링
Station 의 지표 — 명령·기기·컴퓨트.
감사 로그
내 계정의 쓰기 요청 기록.
리소스 (옛 경로)
v0.1.0 의 경로. 새 코드는 기기(/devices)를 쓴다.
/stations/{station_id}/resourcesPOST리소스 등록 (옛 경로)/stations/{station_id}/resourcesGET리소스 조회 (옛 경로)/resources/{resource_id}PATCH리소스 수정 (옛 경로)/resources/{resource_id}DELETE리소스 지우기 (옛 경로)/resources/{resource_id}POST리소스 켜기 (옛 경로)/resources/{resource_id}/enablePOST리소스 끄기 (옛 경로)/resources/{resource_id}/disable에이전트 (옛 경로)
v0.1.0 의 경로. 새 코드는 /devices/{id}/agent·/tools 를 쓴다.
화면 (옛 경로)
v0.1.0 의 경로. 새 코드는 /devices/{id}/screen 을 쓴다.
릴레이 (에이전트 전용)
에이전트가 붙는 WebSocket 과 블롭 업로드 — 사람·프로그램이 부르지 않는다.
Billing costs
Deployment access
Deployments
/deployments/{deployment_id}DELETEdeleteDeployment/deployments/{deployment_id}GETlistDeploymentKeys/deployments/{deployment_id}/api-keysPOSTcreateDeploymentKey/deployments/{deployment_id}/api-keysDELETErevokeDeploymentKey/deployments/{deployment_id}/api-keys/{key_id}POSTprovisionDeployment/deployments/{deployment_id}/provisionGETlistDeploymentReleases/deployments/{deployment_id}/releasesPOSTcreateDeploymentRelease/deployments/{deployment_id}/releasesPOSTdeployRelease/deployments/{deployment_id}/releases/{release_id}/deployPOSTqueryDeploymentDatabase/deployments/{deployment_id}/resources/{resource}/queryPUTputDeploymentResourceSecrets/deployments/{deployment_id}/resources/{resource}/secretsGETlistDeployments/stations/{station_id}/deploymentsPOSTcreateDeployment/stations/{station_id}/deploymentsOS interface
Resource usage
Hosting
OAuth
/me/oauth/grantsDELETErevokeMyOAuthGrant/me/oauth/grants/{grant_id}GETgetOAuthAuthorization/oauth/authorizations/{authorization_id}POSTapproveOAuthAuthorization/oauth/authorizations/{authorization_id}/approvePOSTdenyOAuthAuthorization/oauth/authorizations/{authorization_id}/denyGETgetOAuthMe/oauth/meOrganizations
/orgsPOSTcreateOrg/orgsGETgetOrg/orgs/{org_id}PATCHupdateOrg/orgs/{org_id}DELETEdeleteOrg/orgs/{org_id}GETlistOrgAuditLogs/orgs/{org_id}/audit-logsGETlistOrgMembers/orgs/{org_id}/membersPOSTaddOrgMember/orgs/{org_id}/membersPATCHupdateOrgMember/orgs/{org_id}/members/{user_id}DELETEremoveOrgMember/orgs/{org_id}/members/{user_id}GETlistOrgProjects/orgs/{org_id}/projectsPOSTcreateOrgProject/orgs/{org_id}/projectsGETlistOrgStations/orgs/{org_id}/stationsSecret access
Secrets
/secrets/{secret_id}PATCHupdateSecret/secrets/{secret_id}DELETEdeleteSecret/secrets/{secret_id}GETlistSecretAccessTokens/secrets/{secret_id}/access-tokensPOSTcreateSecretAccessToken/secrets/{secret_id}/access-tokensDELETErevokeSecretAccessToken/secrets/{secret_id}/access-tokens/{access_token_id}GETlistSecretGrants/secrets/{secret_id}/grantsPUTputSecretGrant/secrets/{secret_id}/grants/{subject_type}/{subject_id}DELETEdeleteSecretGrant/secrets/{secret_id}/grants/{subject_type}/{subject_id}POSTrevealSecret/secrets/{secret_id}/revealPUTputSecretValue/secrets/{secret_id}/valueGETlistSecrets/stations/{station_id}/secretsPOSTcreateSecret/stations/{station_id}/secretsOS snapshots
Workspace storage bindings
/snapshots/{snapshot_id}/storage-bindingsPOSTcheckpointWorkspaceStorages/workspaces/{workspace_id}/storage-checkpointsGETgetWorkspaceStorageBindings/workspaces/{workspace_id}/storagesPOSTbindWorkspaceStorage/workspaces/{workspace_id}/storagesPATCHsetDefaultStorageBinding/workspaces/{workspace_id}/storages/defaultPOSTcheckpointStorageBinding/workspaces/{workspace_id}/storages/{storage_id}/checkpointPOSTdetachStorageBinding/workspaces/{workspace_id}/storages/{storage_id}/detachGETreadStorageBindingFile/workspaces/{workspace_id}/storages/{storage_id}/filesPUTwriteStorageBindingFile/workspaces/{workspace_id}/storages/{storage_id}/filesWorkspace storage
/stations/{station_id}/storagesPOSTcreateWorkspaceStorage/stations/{station_id}/storagesGETgetWorkspaceStorage/storages/{storage_id}DELETEdeleteWorkspaceStorage/storages/{storage_id}GETgetWorkspaceStorageBlob/storages/{storage_id}/blobs/{sha256}PUTputWorkspaceStorageBlob/storages/{storage_id}/blobs/{sha256}POSTcheckpointWorkspaceStorage/storages/{storage_id}/checkpointGETgetWorkspaceStorageManifest/storages/{storage_id}/filesPOSTattachWorkspaceStorage/workspaces/{workspace_id}/storage/attachPOSTsyncWorkspaceStorage/workspaces/{workspace_id}/storage/checkpointPOSTdetachWorkspaceStorage/workspaces/{workspace_id}/storage/detachWorkspaces
/stations/{station_id}/workspace-environmentsGETlistWorkspaces/stations/{station_id}/workspacesPOSTcreateWorkspace/stations/{station_id}/workspacesGETgetWorkspace/workspaces/{workspace_id}PATCHupdateWorkspace/workspaces/{workspace_id}DELETEdeleteWorkspace/workspaces/{workspace_id}POSTactivateWorkspace/workspaces/{workspace_id}/activateGETlistWorkspaceBackups/workspaces/{workspace_id}/backupsPOSTcreateWorkspaceBackup/workspaces/{workspace_id}/backupsPOSTcreateWorkspaceCommand/workspaces/{workspace_id}/commandsGETlistWorkspaceFiles/workspaces/{workspace_id}/filesGETreadWorkspaceFile/workspaces/{workspace_id}/files/contentPUTwriteWorkspaceFile/workspaces/{workspace_id}/files/contentPOSTinstallWorkspace/workspaces/{workspace_id}/installGETgetWorkspaceScreen/workspaces/{workspace_id}/screenPOSTcreateWorkspaceSecretTokens/workspaces/{workspace_id}/secret-tokensPOSTstopWorkspace/workspaces/{workspace_id}/stopGETlistWorkspaceTools/workspaces/{workspace_id}/toolsStorage copy, move and links
/storage-links/{link_id}DELETEdeleteStorageLink/storage-links/{link_id}GETreadStorageLinkBlob/storage-links/{link_id}/blobs/{sha256}GETlistStorageLinkFiles/storage-links/{link_id}/filesPOSTcopyIntoStorage/storages/{storage_id}/copiesGETlistStorageLinks/storages/{storage_id}/linksPOSTcreateStorageLink/storages/{storage_id}/linksPOSTmoveIntoStorage/storages/{storage_id}/movesStorage transfer
Scoped storage transfer v2
/storage-transfer/v2/sessions/{session_id}POSTcancelScopedStorageTransfer/storage-transfer/v2/sessions/{session_id}/cancelPOSTcommitScopedStorageTransfer/storage-transfer/v2/sessions/{session_id}/commitPUTputScopedStorageManifestBatch/storage-transfer/v2/sessions/{session_id}/manifest-batches/{batch_number}GETreadScopedStorageBlob/storage-transfer/v2/sessions/{session_id}/revisions/{revision}/blobs/{sha256}POSTcreateScopedStorageUpload/storage-transfer/v2/sessions/{session_id}/uploadsPOSTcompleteScopedStorageUpload/storage-transfer/v2/sessions/{session_id}/uploads/{upload_id}/completeGETlistScopedStorageParts/storage-transfer/v2/sessions/{session_id}/uploads/{upload_id}/partsPUTputScopedStoragePart/storage-transfer/v2/sessions/{session_id}/uploads/{upload_id}/parts/{part_number}Storage history and operations
/storages/{storage_id}/capabilitiesPOSTpreviewStorageCleanup/storages/{storage_id}/cleanup-previewsPOSTcleanupStorage/storages/{storage_id}/cleanupsPOSTcloneWorkspaceStorage/storages/{storage_id}/clonesGETgetStorageOperation/storages/{storage_id}/operations/{operation_id}POSTcancelStorageOperation/storages/{storage_id}/operations/{operation_id}/cancelPOSTrestoreWorkspaceStorage/storages/{storage_id}/restoresGETgetStorageRetention/storages/{storage_id}/retentionPATCHupdateStorageRetention/storages/{storage_id}/retentionGETlistStorageRevisions/storages/{storage_id}/revisionsGETgetStorageRevision/storages/{storage_id}/revisions/{revision}GETreadStorageRevisionBlob/storages/{storage_id}/revisions/{revision}/blobs/{sha256}GETlistStorageRevisionFiles/storages/{storage_id}/revisions/{revision}/filesPUTpinStorageRevision/storages/{storage_id}/revisions/{revision}/pinDELETEunpinStorageRevision/storages/{storage_id}/revisions/{revision}/pinPOSTcreateStorageReadLease/storages/{storage_id}/revisions/{revision}/read-leasesStorage transfer v2
/storages/{storage_id}/transfer-sessionsGETgetStorageTransferSession/storages/{storage_id}/transfer-sessions/{session_id}POSTcancelStorageTransferSession/storages/{storage_id}/transfer-sessions/{session_id}/cancelPOSTcommitStorageTransferSession/storages/{storage_id}/transfer-sessions/{session_id}/commitPUTputStorageManifestBatch/storages/{storage_id}/transfer-sessions/{session_id}/manifest-batches/{batch_number}POSTrenewStorageTransferSession/storages/{storage_id}/transfer-sessions/{session_id}/renewPOSTcreateStorageUpload/storages/{storage_id}/transfer-sessions/{session_id}/uploadsPOSTcompleteStorageUpload/storages/{storage_id}/transfer-sessions/{session_id}/uploads/{upload_id}/completeGETlistStorageUploadParts/storages/{storage_id}/transfer-sessions/{session_id}/uploads/{upload_id}/partsPUTuploadStoragePart/storages/{storage_id}/transfer-sessions/{session_id}/uploads/{upload_id}/parts/{part_number}인증 수단
| 수단 | 어디에 | 누가 · 무엇을 |
|---|---|---|
| 사용자 JWT | Authorization: Bearer <JWT> | endue 계정(셀 신원 공급자 Keycloak). 모든 오퍼레이션 |
| Station API 키 | Authorization: Bearer osk_… 또는 X-API-Key: osk_… | 서버·CI. 자기 Station 안에서만. Station 만들기·지우기, 키 만들기, 클라우드 기기 만들기·지우기는 못 해요(403) |
| 이벤트 입장권 | ?ticket=ostk_… | 브라우저의 EventSource·WebSocket. 1회용, 60초 — 이벤트 |
| 연결 토큰 | ?token=osat_… | 기기의 에이전트만 — 릴레이 소켓·블롭 업로드 |