API
이 문서는 Deplite의 공개 REST API를 정리해요.
프로그램(외부 시스템, CI, 자체 스크립트, 자체 Agent)에서 호출하는 모든 엔드포인트가 대상이에요.
조직·트리거·토큰의 생성과 관리는 대시보드(deplite.io)에서 진행해요.
이 문서는 대시보드에서 받은 트리거 ID와 API Token으로 어떻게 호출하는지에 집중해요.
인증 방식
| 방식 | 헤더 | 용도 |
|---|---|---|
| API Token | Authorization: Bearer dpl_... | 외부 시스템·CI·자동화 스크립트 |
| Agent 서명 | X-Agent-Id, X-Timestamp, X-Nonce, X-Signature | 자체 구현 Agent ↔ Server |
API Token은 대시보드에서 scope(agent / trigger / storage)와 rate limit을 지정해 발급받아요.
평문 토큰은 발급 시점에만 한 번 보이고, 이후엔 복원할 수 없어요.
안전한 비밀 저장소에 보관하세요.
토큰 scope 종류
토큰의 scopes는 grant 배열이고, 각 type은 최대 하나씩 들어가요.
| type | 형태 | 의미 |
|---|---|---|
agent | { type: 'agent', agentIds: string[] } | 지정한 Agent에 대한 권한 |
trigger | { type: 'trigger', triggerIds: string[] } | 지정한 트리거 실행 권한 |
storage | { type: 'storage', bindingIds: string[] | null, permissions: ('read' | 'write' | 'delete')[] } | 지정한 storage binding 접근 권한 (bindingIds: null이면 조직 전체 binding) |
Base URL
- API:
https://api.deplite.io/v1
모든 경로는 위 베이스에 붙여서 호출해요.
이 문서의 경로 표는 베이스 이후의 path만 표기해요.
토큰 접근 범위 조회
토큰이 실제로 무엇에 닿을 수 있는지 토큰 스스로 알려주는 조회 엔드포인트예요.
예전에는 API Token 보유자가 트리거·워크플로우 ID를 항상 외부에서 미리 알고 있어야 했는데, ID는 비밀이 아니므로 grant 범위 안에서의 열거를 허용해 사용성을 개선한 거예요.
| 메서드 | 경로 | 인증 | 설명 |
|---|---|---|---|
| GET | /token | API Token (scope 무관) | 토큰 자기소개 |
| GET | /agents | API Token (scope 무관) | 접근 가능한 device 목록 |
| GET | /devices | API Token (scope 무관) | /agents의 alias, 응답 동일 |
| GET | /workflows | API Token (scope 무관) | 실행 가능한 워크플로우 목록 |
네 엔드포인트 모두 Authorization: Bearer dpl_...만 있으면 호출할 수 있고, 특정 scope를 요구하지 않아요.
응답은 그 토큰의 grant 범위로만 한정돼요.
조직 전체 인벤토리를 돌려주지 않고, 새로운 권한을 부여하지도 않아요.
이미 그 토큰으로 호출할 수 있는 대상만 열거해서 보여주는 엔드포인트예요.
GET /token
호출자가 이미 토큰을 쥐고 있으므로, 그 토큰의 메타만 그대로 돌려줘요.
curl https://api.deplite.io/v1/token \
-H "Authorization: Bearer dpl_..."{
"name": "CI/CD",
"scopes": [
{ "type": "agent", "agentIds": ["a-1111"] },
{ "type": "storage", "bindingIds": null, "permissions": ["read", "write"] }
],
"rateLimit": {
"perMinute": 10,
"perHour": 100,
"perDay": 1000
},
"expiresAt": "2026-12-31T23:59:59Z"
}평문 토큰이나 해시는 응답에 포함되지 않아요.
GET /agents · GET /devices
두 경로는 완전히 같은 응답을 돌려주는 alias예요.
토큰이 닿을 수 있는 device를 최근 등록 순으로 나열해요.
curl https://api.deplite.io/v1/agents \
-H "Authorization: Bearer dpl_..."[
{
"id": "a-1111",
"name": "prod-seoul-01",
"hostname": "ip-10-0-1-23",
"os": "linux",
"agentVersion": "0.1.1",
"status": "connected",
"lastSeenAt": "2026-07-09T02:31:04Z",
"enrolledAt": "2026-05-02T08:12:00Z"
}
]| 필드 | 타입 | 설명 |
|---|---|---|
id | UUID | Agent(device) ID |
name | string | 대시보드에서 지정한 이름 |
hostname | string | Agent가 보고한 호스트명 |
os | string | Agent가 보고한 OS |
agentVersion | string | Agent 버전 |
status | pending | connected | disconnected | revoked | 현재 연결 상태 |
lastSeenAt | timestamp | 마지막 하트비트 시각 |
enrolledAt | timestamp | 등록 완료 시각 |
GET /workflows
토큰으로 실행할 수 있는 워크플로우를 이름 오름차순으로 나열해요.
curl https://api.deplite.io/v1/workflows \
-H "Authorization: Bearer dpl_..."[
{
"id": "w-2222",
"agentId": "a-1111",
"name": "deploy",
"description": "프로덕션 배포",
"version": "1.2.0",
"paramsSchema": [
{
"name": "env",
"type": "enum",
"required": true,
"options": ["staging", "prod"]
}
]
}
]| 필드 | 타입 | 설명 |
|---|---|---|
id | UUID | 워크플로우 ID |
agentId | UUID | 이 워크플로우가 속한 Agent |
name | string | 워크플로우 이름. 트리거 호출 시 workflowName으로 넘기는 값 |
description | string | null | 워크플로우 설명 |
version | string | null | Agent가 워크플로우 정의에서 보고한 자유 문자열. semver를 강제하지 않아 "1.2.0", "2024-06-rc1" 같은 임의 값이 올 수 있고, 정의에 없으면 null |
paramsSchema | array | null | 입력 파라미터 정의 배열. 각 항목은 name·type(string | number | boolean | enum)을 갖고, required·default·pattern·options·min·max·description이 선택으로 붙어요 |
removed 상태(제거된) 워크플로우는 목록에 나오지 않아요.
grant → 노출 범위 매핑
/agents와 /workflows가 무엇을 보여줄지는 토큰의 grant 조합으로 결정돼요.
| 토큰이 가진 grant | /agents에 보이는 것 | /workflows에 보이는 것 |
|---|---|---|
agent grant | grant에 적힌 Agent | 그 Agent의 모든 active 워크플로우 |
trigger grant — 트리거가 scopeType: agent | 트리거가 가리키는 Agent | 그 Agent의 모든 active 워크플로우 |
trigger grant — 트리거가 scopeType: workflow | 트리거가 가리키는 Agent | 그 트리거의 워크플로우 1개 |
storage grant만 있는 토큰 | 빈 배열 | 빈 배열 |
응답에서 의도적으로 빠지는 필드
민감 정보 누출을 막기 위해 아래 필드는 어떤 경우에도 응답에 담기지 않아요.
| 리소스 | 제외되는 필드 |
|---|---|
| Agent | publicKey |
| Trigger | tokenHash |
| Workflow | secrets, secretsKeys, steps |
paramsSchema는 비밀이 아니라 입력 파라미터 정의라서, 호출 편의를 위해 포함돼요.
에러와 rate limit
| HTTP | 상황 |
|---|---|
| 401 | 토큰 누락 / 무효 / 폐기됨 / 만료됨 |
| 429 | 읽기 rate limit 초과 |
읽기 rate limit은 토큰의 rateLimitPerMinute(Job 디스패치 한도)와는 별개예요.
기본값은 토큰당 분당 60회이고, 서버 환경변수 API_TOKEN_READ_RATE_LIMIT_PER_MINUTE로 조정해요.
{
"statusCode": 429,
"error": "Too Many Requests",
"message": "Rate limit exceeded for api token reads (minute: 61/60)",
"scope": "token_read",
"window": "minute",
"limit": 60,
"observed": 61
}셀프 호스팅 운영 주의: 이 카운터는 인스턴스 메모리에 있어서, 다중 인스턴스 배포에서는 인스턴스당 한도로 동작해요.
전역 한도가 아니라 열거(enumeration) 폭주를 늦추는 완화책으로 봐주세요.
감사 로그
| 호출 | 남는 audit 로그 |
|---|---|
/agents, /devices, /workflows | api_token.discover (metadata: { resource, count }) |
/token | 기록하지 않음 |
| 읽기 rate limit에 걸린 호출 | rate_limit.block (scope: 'token_read'), 토큰당 윈도우 1회만 기록 |
rate_limit.block을 윈도우당 1회로 제한하는 이유는, 폭주하는 호출이 audit 테이블에 쓰기 증폭을 일으키지 않도록 하기 위해서예요.
Trigger 실행
| 메서드 | 경로 | 인증 | 설명 |
|---|---|---|---|
| POST | /triggers/:id/run | API Token (trigger scope) | Webhook 실행 |
POST /triggers/:id/run
curl -X POST https://api.deplite.io/v1/triggers/<id>/run \
-H "Authorization: Bearer dpl_..." \
-H "Idempotency-Key: <unique>" \
-d '{
"ref": "main",
"debug": false,
"workflowName": "deploy",
"params": { "env": "prod" }
}'요청 본문 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
ref | string, 선택 | 호출자 측에서 식별·로깅에 쓰는 ref (1–255자). 보통 git SHA / 태그 |
debug | boolean, 선택 | 디버그 모드 실행 |
params | object, 선택 | 워크플로우 step에 그대로 전달되는 임의 페이로드 |
workflowName | string, 선택 | scopeType: agent인 트리거에서는 필수, scopeType: workflow에선 무시 |
응답 (async, responseMode: async):
{
"jobId": "j-abc-1234",
"status": "pending",
"statusUrl": "/api/jobs/j-abc-1234"
}응답 (sync, responseMode: sync):
{
"jobId": "j-abc-1234",
"status": "success",
"exitCode": 0,
"errorMessage": null,
"output": { "deployedRef": "main-7f3a9b" },
"statusUrl": "/api/jobs/j-abc-1234"
}Idempotency-Key가 이전 호출과 같으면 같은 jobId로 "idempotent": true 플래그를 붙여 돌려줘요.
sync 모드에서 responseTimeoutMs를 초과한 경우 "timedOut": true가 붙고 워크플로우는 백그라운드에서 계속 진행돼요.
statusUrl의 /api/jobs/...는 대시보드 콘솔 URL이라 API Token으로는 호출할 수 없어요.
외부에서 결과를 받는 방법은 두 가지예요.
responseMode: sync 트리거로 만들어 /run 응답에서 바로 꺼내 쓰거나, 트리거의 notify… 옵션으로 Slack/Discord 알림을 받는 방식이에요.
공개 v1 API에는 GET /jobs/... 엔드포인트가 없으니, Job 상세는 대시보드 Jobs 화면에서 확인해주세요.
File Storage
외부 시스템(CI 파이프라인 등)이 파일을 업로드·교환할 때 쓰는 공개 API예요.
인증은 storage 스코프가 부여된 API Token이며, 토큰은 하나 이상의 storage binding에 묶여 있어요.
| 메서드 | 경로 | 인증 | 설명 |
|---|---|---|---|
| POST | /storage/files/presign-upload | storage 스코프 + write | 업로드 사전 서명 URL 발급 |
| POST | /storage/files/:id/complete | storage 스코프 + write | 업로드 완료 통지 |
| GET | /storage/files/:id/download-url | storage 스코프 + read | 다운로드 사전 서명 URL |
| GET | /storage/files/:id | storage 스코프 + read | 파일 메타 |
| GET | /storage/files | storage 스코프 + read | 파일 목록 (최대 200건) |
| DELETE | /storage/files/:id | storage 스코프 + delete | 파일 삭제 |
storage 스코프 토큰은 발급 시 { type: 'storage', bindingIds: [...], permissions: ['read', 'write', 'delete'] } 형태로 binding과 허용 권한을 함께 지정해요.
권한은 배열이라 read 전용 / read+write / 전체 등 자유 조합이 가능해요.
POST /storage/files/presign-upload
요청 본문:
{
"bindingId": "<uuid, 선택>",
"filename": "release.apk",
"contentType": "application/vnd.android.package-archive",
"cleanupRule": "ttl",
"ttlSeconds": 604800
}| 필드 | 타입 | 설명 |
|---|---|---|
bindingId | UUID, 선택 | 어느 storage binding을 쓸지. 토큰이 단일 binding만 허용한다면 생략 가능 |
filename | string, 선택 | 원본 파일명 힌트 (max 255) |
contentType | string, 선택 | MIME 타입 (max 255) |
cleanupRule | "ttl" | "persistent", 필수 | 외부 API는 on_job_end 미지원 |
ttlSeconds | int, 선택 | cleanupRule: ttl일 때 60 ~ 90일 사이 |
응답:
{
"fileId": "f-abc-1234",
"uploadUrl": "https://...presigned...",
"method": "PUT",
"headers": { "Content-Type": "application/vnd.android.package-archive" },
"expiresInSeconds": 900
}받은 uploadUrl로 곧바로 PUT 한 뒤, 같은 fileId로 /complete를 호출해야 파일이 active 상태가 돼요.
POST /storage/files/:id/complete
본문 없이 호출해요.
응답은 아래 메타 스키마와 동일해요.
GET /storage/files/:id/download-url
{
"downloadUrl": "https://...presigned...",
"expiresInSeconds": 900
}다운로드 URL은 매 호출마다 새로 발급돼요.
워크플로우에 넘길 때는 호출 직전에 받아 params로 전달하세요.
GET /storage/files
쿼리:
| 파라미터 | 설명 |
|---|---|
bindingId | UUID, 단일 binding으로 필터 |
status | pending | active | deleting | deleted | delete_failed |
응답은 메타 배열이에요 (최대 200건).
파일 메타 응답 스키마
{
"id": "f-abc-1234",
"bindingId": "sb-...",
"filename": "release.apk",
"contentType": "application/vnd.android.package-archive",
"size": 28473921,
"status": "active",
"cleanupRule": "ttl",
"expiresAt": "2026-06-09T12:00:00Z",
"deletedAt": null,
"createdAt": "2026-06-02T12:00:00Z"
}외부 API 응답에는 organizationId·jobId 같은 내부 필드가 빠져 있어요.
토큰의 binding 권한 범위에서만 메타가 보여요.
App Deploy (OTA)
기존 트리거 배포는 서버가 Agent에게 실행을 밀어 넣는 방식이라, Agent가 오프라인이면 그 실행은 곧바로 거절돼요.
App Deploy(OTA)는 Deplite가 배포 서버 역할을 맡아 아티팩트를 조직 스토리지에 보관하고, 기기가 온라인이 될 때 스스로 최신 릴리스로 수렴하게 해요.
키오스크처럼 항상 켜져 있지 않은 기기에 배포할 때 참고해주세요.
설치·재시작 같은 적용 로직은 여전히 여러분의 로컬 워크플로우(예: app-update)에만 있어요.
서버는 “이 아티팩트를 파라미터로 넣어 기기의 로컬 워크플로우를 실행한다”까지만 관여하고, 어떻게 적용할지는 워크플로우가 결정해요.
인증과 경로
App Deploy 엔드포인트는 두 부류로 나뉘어요.
| 부류 | 인증 | 경로 |
|---|---|---|
| 대시보드 관리 | 대시보드 로그인 세션(JWT) + 조직 role | /orgs/:orgId/apps/... |
| Agent 배포 | Agent 서명 (X-Agent-Id, X-Timestamp, X-Nonce, X-Signature) | /agent/deploy/... (베이스 https://api.deplite.io/v1) |
대시보드 관리 엔드포인트는 앱·릴리스·기기를 만들고 운영하는 콘솔 API예요.
조직 role로 인가되고, 삭제처럼 되돌리기 어려운 작업은 owner만 할 수 있어요.
앱 (Apps)
| 메서드 | 경로 | 인증 | 설명 |
|---|---|---|---|
| GET | /orgs/:orgId/apps | 세션 + 조직 role | 앱 목록 |
| POST | /orgs/:orgId/apps | 세션 + 조직 role | 앱 생성 |
| GET | /orgs/:orgId/apps/:appId | 세션 + 조직 role | 앱 상세 |
| PATCH | /orgs/:orgId/apps/:appId | 세션 + 조직 role | 앱 수정 |
| DELETE | /orgs/:orgId/apps/:appId | 세션 + owner | 앱 삭제 |
앱을 만들 때 지정하는 값이에요.
| 필드 | 타입 | 설명 |
|---|---|---|
slug | string | 조직 안에서 유일한 앱 식별자 |
updateWorkflowName | string | 업데이트를 적용할 로컬 워크플로우 이름 (예: app-update) |
defaultChannel | string | 기기가 구독할 기본 채널. 기본값은 stable |
릴리스 (Releases)
| 메서드 | 경로 | 인증 | 설명 |
|---|---|---|---|
| GET | /orgs/:orgId/apps/:appId/releases | 세션 + 조직 role | 릴리스 목록 (?channel=&status=) |
| POST | /orgs/:orgId/apps/:appId/releases | 세션 + 조직 role | 릴리스 생성 (draft) |
| GET | /orgs/:orgId/apps/:appId/releases/:releaseId | 세션 + 조직 role | 릴리스 상세 |
| POST | /orgs/:orgId/apps/:appId/releases/:releaseId/publish | 세션 + 조직 role | 게시 |
| POST | /orgs/:orgId/apps/:appId/releases/:releaseId/yank | 세션 + 조직 role | 회수(롤백) |
릴리스는 아티팩트(스토리지 파일)를 가리키는 배포 단위예요.
게시(publish)하면 그 채널의 기기들이 다시 평가되어 최신 릴리스로 수렴하기 시작해요.
회수(yank)하면 대상 채널의 desired가 직전 게시본으로 내려가고, 기기들이 그쪽으로 수렴해요(다운그레이드).
회수는 롤백 수단이므로, 로컬 워크플로우가 다운그레이드를 감당할 수 있는지 확인해주세요.
게시된 릴리스는 불변이에요.
순서는 사람이 읽는 version 문자열이 아니라 앱 단위로 증가하는 sequence로 판단해요.
updatePolicy가 mandatory인 릴리스는 최소 버전 마커가 되어, 그보다 낮은 기기는 강제로 업데이트돼요.
optional이면 최신으로 수렴하되 기기가 미룰 수 있어요.
릴리스용 아티팩트는 cleanupRule: 'persistent'로 업로드해야 릴리스 생성이 통과해요.
릴리스가 참조 중인 파일은 삭제가 409로 막혀요.
그 파일을 지우려면 해당 릴리스를 먼저 회수(yank)해주세요.
기기 (Devices)
| 메서드 | 경로 | 인증 | 설명 |
|---|---|---|---|
| GET | /orgs/:orgId/apps/:appId/devices | 세션 + 조직 role | 기기(바인딩) 목록 |
| POST | /orgs/:orgId/apps/:appId/devices | 세션 + 조직 role | 앱에 Agent 바인딩 |
| PATCH | /orgs/:orgId/apps/:appId/devices/:deviceId | 세션 + 조직 role | 기기 채널 변경 |
| DELETE | /orgs/:orgId/apps/:appId/devices/:deviceId | 세션 + 조직 role | 바인딩 해제 |
| POST | /orgs/:orgId/apps/:appId/devices/:deviceId/reconcile | 세션 + 조직 role | 수동 재평가 |
기기는 앱과 Agent를 묶은 바인딩이고, 관측된 현재 설치본과 희망 릴리스 상태를 담아요.
바인딩을 만들 때 channel을 생략하면 앱의 기본 채널을 따라요.
reconcile은 기기의 desired를 지금 다시 계산해서 필요하면 업데이트 job을 다시 발생시키는 수동 재평가예요.
기기 바인딩 요청 본문:
{ "agentIds": ["a-1111", "a-2222"], "channel": "stable" }채널 변경 요청 본문:
{ "channel": "beta" }| 필드 | 타입 | 설명 |
|---|---|---|
agentIds | string[] | 앱에 바인딩할 Agent ID 목록 |
channel | string, 선택 | 구독할 채널. 생략하면 앱의 기본 채널 |
OTA 업데이트 job은 트리거로 생성되지 않아 triggerId가 없어요.
그래서 트리거 job 목록(GET /orgs/:orgId/jobs)에는 나타나지 않아요.
진행 중인 job은 기기의 activeJobId로 해당 job 상세(GET /jobs/:id)에 접근해주세요.
Agent 배포 엔드포인트
Agent가 자기 배포 상태를 확인하고 보고하는 엔드포인트예요.
Agent 서명으로 인증해요.
| 메서드 | 경로 | 인증 | 설명 |
|---|---|---|---|
| GET | /agent/deploy/desired | Agent 서명 | 각 앱의 서명된 desired 매니페스트 |
| POST | /agent/deploy/report | Agent 서명 | 현재 설치 상태 보고 |
curl https://api.deplite.io/v1/agent/deploy/desired \
-H "X-Agent-Id: <agentId>" \
-H "X-Timestamp: <timestamp>" \
-H "X-Nonce: <nonce>" \
-H "X-Signature: <signature>"응답은 Agent가 담당하는 앱마다 서명된 매니페스트 1개를 담아요.
{ "apps": [{
"payload": {
"application_id": "...", "slug": "kiosk", "channel": "stable",
"update_workflow": "app-update",
"current": { "release_id": "...", "version": "1.1.0", "sequence": 1 },
"desired": {
"release_id": "...", "version": "1.2.0", "sequence": 2, "channel": "stable",
"workflow_name": "app-update", "checksum_sha256": "...", "size": 10485760,
"download_url": "https://...", "download_expires_in": 900
},
"min_version": "1.2.0", "min_sequence": 2, "forced": true,
"issued_at": 1750000000, "nonce": "..."
},
"signature": "<base64 서명>"
}]}current는 서버가 관측한 현재 설치본, desired는 기기가 수렴해야 할 목표 릴리스예요.
signature는 payload를 canonical JSON으로 직렬화한 값에 대한 서명이에요.
Agent는 등록(enroll) 때 받은 서버 공개키(serverPublicKey)로 이 서명을 검증해요.
download_url은 매 발급마다 새로 만들어지고 download_expires_in(초) 뒤 만료돼요.
이 매니페스트는 서버가 밀어 준 job의 pull 폴백이자 Agent 자가 점검용이니 참고해주세요.
report는 Agent가 관측한 현재 설치 상태를 보고하는 엔드포인트예요.
{
"applicationId": "...",
"currentVersion": "1.1.0",
"currentReleaseId": "...",
"currentSequence": 1,
"state": "idle",
"error": null
}| 필드 | 타입 | 설명 |
|---|---|---|
applicationId | string | 보고 대상 앱 |
currentVersion | string, 선택 | 현재 설치된 버전 라벨 |
currentReleaseId | string, 선택 | 현재 설치된 릴리스 |
currentSequence | int, 선택 | 현재 설치된 릴리스의 순서 값 |
state | string, 선택 | 기기가 관측한 적용 상태 |
error | string, 선택 | 적용 중 발생한 오류 |
보고를 받으면 서버가 곧바로 재평가해요.
그래서 Agent가 처음 접속했을 때 기준선을 맞추는 용도로도 쓸 수 있어요.
update job의 deploy 파라미터
OTA 업데이트가 발생하면 Agent는 기존 SSE deploy 이벤트를 받아요.
그 params는 다음과 같아요.
{ "artifact": { "__type": "FileRef", "id": "...", "downloadUrl": "https://..." },
"release_id": "...", "version": "1.2.0", "channel": "stable",
"sequence": 2, "forced": true, "checksum_sha256": "..." }| 필드 | 타입 | 설명 |
|---|---|---|
artifact | object | 내려받을 아티팩트 참조. downloadUrl은 전송할 때마다 새로 주입돼요 |
release_id | string | 적용할 릴리스 |
version | string | 릴리스 버전 라벨 |
channel | string | 릴리스 채널 |
sequence | int | 릴리스 순서 값 |
forced | boolean | 강제 업데이트 여부. 판단은 서버가 하고, 집행(앱 차단 등)은 Agent가 해요 |
checksum_sha256 | string | 다운로드 후 무결성 검증용 체크섬 |
forced 여부와 무관하게, 아티팩트를 받아 어떻게 적용할지는 여러분의 로컬 워크플로우가 결정해요.
checksum_sha256으로 내려받은 파일을 검증한 뒤 적용해주세요.
에러 응답
{
"statusCode": 429,
"code": "rate_limited",
"message": "Rate limit exceeded",
"retryAfter": 42
}| HTTP | 상황 |
|---|---|
| 401 | 토큰 없음/무효 |
| 403 | 권한 부족 (스코프 불일치 등) |
| 404 | 리소스 없음 |
| 409 | 중복 (idempotency 충돌 등) |
| 422 | 입력 검증 실패 |
| 429 | 레이트 리밋 초과 |
| 500 | 서버 에러 |
리밋·큐로 거부되어 Job 자체가 rejected가 되는 경우는 제한과 정책에서 다뤄요.
토큰 접근 범위 조회 엔드포인트의 429는 본문 형태가 달라요(scope: "token_read").
사용 흐름 예시 — Sync 모드 Webhook
외부 API Token으로 결과까지 한 번에 받는 가장 단순한 패턴이에요.
responseMode: sync로 만들어 둔 트리거를 호출하면 워크플로우 완료까지 기다린 응답이 그대로 와요.
TRIGGER_ID="t-xxxxxxxx" # 대시보드 → Triggers → 상세에서 복사
TOKEN="dpl_..." # 대시보드 → API Tokens → 발급 모달의 평문 1회 노출값
RESP=$(curl -fsS -X POST https://api.deplite.io/v1/triggers/$TRIGGER_ID/run \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"ref": "main", "params": {"replicas": "3"}}')
echo "$RESP" | jq '{ jobId, status, exitCode, output, timedOut }'응답 예:
{
"jobId": "j-abc-1234",
"status": "success",
"exitCode": 0,
"output": { "deployedRef": "main-7f3a9b", "url": "https://app.example.com" }
}responseTimeoutMs를 넘기면 "timedOut": true가 붙어요.
이 경우 워크플로우는 계속 실행되지만, 결과를 외부에서 받으려면 트리거의 notify… 옵션으로 Slack/Discord 알림을 받거나 대시보드 Jobs 화면에서 확인해야 해요.
비동기(responseMode: async) 트리거를 쓰는 경우는 응답의 jobId로 식별만 가능하고, 결과 전달은 마찬가지로 notify 또는 대시보드에서 확인하는 흐름이에요.