---
title: REST API
description: NexCMP 설치의 고객 API 호출 방법(인증, 대화형 레퍼런스, OpenAPI 및 Postman 다운로드, 오류, 요청 제한, 멱등성 및 curl 예제)에 대해 알아보세요.
url: https://nexcmp.com/ko/docs/developers/api/
applies_to: NexCMP 1.6.1
updated: 2026-11-02
---

# REST API

> **포털 위치:** `https://<your-domain>/apidoc`의 API 참조 (공개) 및 `/api-keys`의 API 키. **관리자 위치:** Customers › API keys (`/customers/apikeys`)에는 고객이 생성한 키가 나열됩니다.

## 작동 내용 {#what-it-does}

고객이 포털에서 수행할 수 있는 모든 작업(VM 목록 조회 및 제어, 인프라 관리, 청구서 읽기, SSH 키 관리, Kubernetes, 스토리지, 지원 티켓)은 `https://<your-domain>/v1/` 아래의 버전이 지정된 REST API를 통해 사용할 수 있습니다. 고객은 범위가 지정된 **API key**를 사용하여 스크립트와 CI에서 이를 호출합니다. 동일한 API가 [`cmp` command-line tool](https://nexcmp.com/ko/docs/developers/cmp-cli/) 및 [MCP server](https://nexcmp.com/ko/docs/developers/mcp/)에 전송되며, 레퍼런스는 실행 중인 설치에서 생성되므로 활성화한 기능이 정확히 나열됩니다.

## 요구 사항 {#requirements}

| 항목 | 요구 사항 |
|---|---|
| 공용 HTTPS 주소 | API는 기본 도메인(및 각 리셀러의 고유 도메인)에서 서비스됩니다. |
| API 키 | 포털에서 고객이 생성합니다. [API keys](https://nexcmp.com/ko/docs/developers/api-keys/)을(를) 참조하세요. |
| 의존성 | 없음. 활성화하지 않은 모듈(예: Kubernetes 또는 Object Storage)의 엔드포인트는 레퍼런스에서 숨겨지고 거부됩니다. |

## 인프라 준비 {#prepare-the-infrastructure}

설치할 내용이 없습니다. NexCMP 앞에 리버스 프록시가 있는 경우 `/v1/`, `/mcp`, `/cli/` 및 `/apidoc`을(를) 패널로 전달하세요(설치 프로그램의 nginx 구성이 이미 처리합니다).

## NexCMP에서 연결 {#connect-in-nexcmp}

### 대화형 레퍼런스 {#the-interactive-reference}

`https://cloud.example.com/apidoc`을(를) 엽니다(호스트를 도메인으로 교체하세요. 리셀러의 고객은 리셀러의 이름과 함께 리셀러의 도메인에서 레퍼런스를 보게 됩니다). 여기에는 curl, `cmp` CLI, JavaScript, Python, Go의 요청 및 응답 예제가 포함된 엔드포인트 문서, 검색 상자(Ctrl 또는 Cmd + K), **Try it** 패널이 있습니다. Try it은 방문자가 붙여넣은 키(브라우저 세션에 유지됨)를 사용하여 동일한 사이트에만 요청을 보냅니다. 기본적으로 읽기 전용이며, 쓰기 또는 유료 호출에는 추가 스위치와 확인이 필요합니다.


### 다운로드 및 기계 판독 가능 문서 {#downloads-and-machine-readable-documents}

모두 공개되어 있으며 키가 필요 없고 사이트별로 생성됩니다:

| URL | 내용 |
|---|---|
| `/apidoc` | 대화형 레퍼런스. |
| `/v1/public/openapi.json` | OpenAPI 3.1 문서. |
| `/v1/public/openapi.yaml` | 동일, YAML. |
| `/v1/public/postman.json` | Postman 컬렉션. |
| `/v1/public/insomnia.json` | Insomnia 내보내기. |
| `/v1/public/api.md` | 단일 Markdown 파일 형태의 레퍼런스. |
| `/v1/public/api-catalog` | 가벼운 JSON: 브랜드, 기본 URL, 키 접두사, 모든 범위, 그리고 메서드, 경로, 범위 및 `Idempotency-Key`이 필요한지 여부가 포함된 모든 엔드포인트. |

```bash
curl -s https://cloud.example.com/v1/public/api-catalog | python3 -m json.tool | head -40
curl -sO https://cloud.example.com/v1/public/openapi.yaml
```

Postman에서 **Import › Link**를 선택하고 `https://cloud.example.com/v1/public/postman.json`을(를) 붙여넣습니다. 참조 페이지에서는 JavaScript 및 Python용 단일 파일 API 클라이언트도 제공합니다.

### 인증 {#authentication}

`Authorization` 헤더에 키를 전송합니다.

```bash
curl -s https://cloud.example.com/v1/billing/wallet \
  -H "Authorization: Bearer vk_XXXX"
```

- 고객 키는 `vk_`(으)로 시작합니다. 키는 **사이트 귀속형**입니다. `cloud.example.com`에서 생성된 키는 리셀러 도메인에서 작동하지 않습니다.
- 브라우저 세션 토큰(`pt_...`)은 포털 전용이므로, 자동화 작업에는 키를 사용하세요.
- 키의 **권한(scope)**에 따라 호출 가능한 작업이 결정되며, 누락된 권한은 HTTP 403 `scope_required`을(를) 반환합니다. [API keys](https://nexcmp.com/ko/docs/developers/api-keys/)을(를) 참조하세요.
- `GET /v1/apikeys/self`을(를) 사용하여 키를 확인하세요. 호출하는 키의 이름, 권한, 만료일 및 남은 요청 제한 허용량(모든 키로 호출 가능)을 반환합니다.

### 예제 {#examples}

```bash
# List virtual machines
curl -s "https://cloud.example.com/v1/vm?page=1" -H "Authorization: Bearer vk_XXXX"

# Start one (needs vm:write)
curl -s -X POST https://cloud.example.com/v1/vm/3f2a1c9e-0000-4000-8000-000000000000/start \
  -H "Authorization: Bearer vk_XXXX"

# Create a VM (paid: needs vm:create and an Idempotency-Key)
curl -s -X POST https://cloud.example.com/v1/vm \
  -H "Authorization: Bearer vk_XXXX" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d @vm.json
```

`/apidoc`에서 각 작업의 정확한 요청 필드를 확인하세요.

### 오류 {#errors}

모든 오류는 고정된 `code` 및 사람이 읽을 수 있는 `message`(이)가 포함된 JSON입니다.

```json
{"error": {"code": "scope_required", "message": "Key lacks scope vm:write"}}
```

| HTTP | 일반적인 `code` | 의미 |
|---|---|---|
| 401 | `unauthenticated`, `key_invalid`, `key_revoked`, `key_expired`, `key_ip_denied`, `site_mismatch`, `api_keys_disabled` | 키 누락 또는 알 수 없음, 철회됨, 만료됨, 키의 허용 목록에 없는 발신자 IP, 다른 사이트의 키 또는 API 키 비활성화. |
| 403 | `scope_required`, `endpoint_not_public`, `account_blocked`, `quota_exceeded`, `impersonate_forbidden` | 키에 권한이 없음; 엔드포인트를 키에서 사용할 수 없음; 계정이 잠김; [quota](https://nexcmp.com/ko/docs/billing/quotas/)에 도달함; 대행(impersonated) 세션에서는 허용되지 않는 작업. |
| 404 | `not_found` | 찾을 수 없음 — 다른 사용자의 리소스인 경우에도 반환됩니다. |
| 422 | `invalid_argument` | 유효성 검사 오류 (응답에 필드 이름이 명시됨). |
| 429 | `rate_limited` | 요청이 너무 많습니다. `Retry-After` 동안 기다려 주세요. |
| 503 | `maintenance` | 유지보수 모드가 켜져 있습니다. 읽기는 가능하지만 쓰기는 거부됩니다. |

### 요청 제한 {#rate-limits}

| 제한 | Default |
|---|---|
| 키당 | 분당 120회 요청 |
| 계정당 (모든 키 합산) | 분당 300회 요청 |

모든 응답에는 `X-RateLimit-Limit`, `X-RateLimit-Remaining` 및 `X-RateLimit-Reset`이(가) 포함되며, 429 응답에는 `Retry-After`이(가) 추가됩니다.

### 멱등성 {#idempotency}

비용이 발생하거나 반복할 수 없는 명령(생성, 요금제 변경, 구매, 삭제 등)에는 `Idempotency-Key` 헤더가 **필수**입니다(200자 이내의 임의 문자열; UUID가 적합합니다). 타임아웃 후에 동일한 키로 다시 전송하면 서버는 작업을 반복하는 대신 (`Idempotency-Replayed: 1`과(와) 함께) **원본** 결과를 반환합니다. 다른 명령에 키를 재사용하면 422를 반환하고, 아직 진행 중인 요청은 409/`Retry-After`를 반환합니다. 헤더가 없으면 유료 호출이 거부됩니다.

## 확인 {#verify}

1. 포털에서 `vm:read` 범위의 키를 생성합니다 (**API keys › Create key**).
2. 실행:

   ```bash
   curl -i https://cloud.example.com/v1/apikeys/self -H "Authorization: Bearer vk_XXXX"
   ```

   HTTP 200과 요청 제한 헤더를 받게 됩니다.
3. `curl -s https://cloud.example.com/v1/vm -H "Authorization: Bearer vk_XXXX"`은(는) 계정의 VM 목록을 조회합니다. 포털의 키 **Last used** 열과 **Key usage log**에서 호출 내역을 확인할 수 있습니다.

## 한도 및 참고 사항 {#limits-notes}

- **키로 절대 사용할 수 없는 작업:** 잔액 충전, 출금, 카드 변경 또는 자동 충전, 비밀번호·이메일·2FA 변경, 계정 삭제, 다른 키 생성·편집·철회. 이러한 작업에는 로그인된 브라우저 세션이 필요합니다.
- **숨겨진 모듈:** 참조 문서와 OpenAPI 문서에는 해당 사이트에서 활성화된 기능만 나열됩니다.
- **응답 크기 및 페이징:** 목록 조회 엔드포인트는 페이징 처리가 적용됩니다(`page`, `per_page`). 각 엔드포인트에 대한 OpenAPI 문서를 참조하세요.
- **시간 및 금액:** 필드 이름에 별도의 언급이 없는 한 금액은 USD 센트 단위입니다.
- **관리자 API:** 관리자 콘솔에는 자체적인 **System › Admin › API** 페이지와 관리를 위한 관리자 키(`ofw_...`)가 있으며, 여기서 설명하는 고객 API와는 별개입니다.
- **버전 관리:** 경로 접두사 `/v1`은(는) 안정적이며, 응답에 새 필드가 추가될 수 있습니다.

## Troubleshooting {#troubleshooting}

| 증상 | 원인 | 해결 방법 |
|---|---|---|
| 새 키 사용 시 401 오류 | 다른 도메인의 키이거나, 만료되었거나, 공백이 포함되어 입력됨 | 호출하는 도메인에서 키를 생성하고 `Authorization: Bearer vk_...` 헤더를 확인하세요. |
| 403 `scope_required` | 스코프 누락 | 포털에서 키를 편집하고 스코프를 추가하세요. |
| 401 `key_ip_denied` 또는 `site_mismatch` | 다른 IP로 제한된 키("허용된 IP")이거나 다른 도메인에서 생성됨 | 키의 허용된 IP에 서버 IP를 추가하거나, 키가 생성된 도메인을 호출하세요. |
| 존재하는 VM에 대한 404 | 다른 계정 소유의 VM임 | 소유자의 키를 사용하세요. |
| `Idempotency-Key`을(를) 요구하는 400/422 | 헤더가 없는 유료 작업 | `Idempotency-Key: <uuid>`을(를) 추가하세요. |
| 429 | 한도 초과 | 요청을 줄이거나 `Retry-After`을(를) 사용하세요. |
| `/apidoc`의 표시 값이 예상보다 적음 | 모듈이 꺼져 있음 | License & updates에서 모듈을 활성화하세요. |


