커넥트 API 레퍼런스
엔드포인트별 요청 파라미터, 응답 필드, 오류 코드를 정리했습니다.
단계별 설명은 가이드에서, 직접 실행할 수 있는 도구는 샌드박스에서 확인할 수 있습니다.
기본 정보
| 기본 URL | https://ai-market.co.kr. 승인 화면과 API 호출 모두 이 주소를 사용합니다. |
| 인가 방식 | OAuth 2.0 인가 코드 방식을 사용합니다. PKCE(S256)는 선택 사항이며, 발급한 토큰은 폐기 API를 통해 언제든 무효화할 수 있습니다. |
| 요청 본문 | 토큰 발급 및 폐기: application/x-www-form-urlencoded.사용량 보고: application/json(폼 인코딩 형식도 지원). |
| 응답 | 응답은 항상 JSON(UTF-8) 형식입니다. 시간은 한국 시간 오프셋을 포함한 ISO 8601 형식( 2026-09-22T19:30:02+09:00)이며, ID는 UUID 문자열, 금액은 원(KRW) 단위입니다. |
mode | 구독과 사용량 응답의 mode는 live(운영 키) 또는 test(테스트 키)입니다.테스트 키 응답에 대한 자세한 내용은 테스트 키 응답 규칙을 참고하세요. |
인증 방식
| 구분 | 자격 증명 | 사용하는 곳 |
|---|---|---|
| 클라이언트 인증 | client_id + client_secret(폼 필드) | /token, /revoke. 서버에서만 요청을 전송합니다. |
| 사용자 자격 | Authorization: Bearer {access_token} | /subscription, /usage |
| 브라우저 세션 | AI Market 사용자 로그인 세션 | /connect/authorize 승인 화면 |
요청 한도와 유효 기간
| 대상 | 값 |
|---|---|
POST /token, POST /revoke | 클라이언트당 분당 30회. 요청 한도 초과 시 429로 응답합니다. |
GET /subscription | 분당 300회 |
GET /usage, POST /usage | 각각 분당 300회 |
| 인가 코드 | 10분, 1회 사용 |
| 접근 토큰 / 갱신 토큰 | 30일 / 180일. 갱신 시 기존 접근 토큰과 갱신 토큰은 즉시 무효화됩니다. |
| 리다이렉트 URI | 키당 최대 10개. http 또는 https 절대 주소만 등록할 수 있으며, # 프래그먼트는 사용할 수 없습니다.요청의 redirect_uri는 등록된 값과 정확히 일치해야 합니다. |
키와 토큰의 접두사
| 값 | 운영 키 | 테스트 키 |
|---|---|---|
| client_id | nxc_… | nxc_test_… |
| client_secret | nxs_… | nxs_test_… |
| 인가 코드 | nxac_… | nxac_test_… |
| 접근 토큰 | nxa_… | nxa_test_… |
| 갱신 토큰 | nxr_… | nxr_test_… |
승인 화면
/connect/authorize브라우저에서 해당 주소로 이동합니다. 서버 간 요청으로 처리하지 않습니다.
사용자가 로그인 후 승인하면 등록된 redirect_uri로 인가 코드가 전달됩니다.
| 쿼리 파라미터 | 필수 | 설명 |
|---|---|---|
client_id | 필수 | 운영 키 또는 테스트 키의 클라이언트 ID |
redirect_uri | 필수 | 등록된 리다이렉트 URI와 정확히 일치하는 값(URL 인코딩) |
service_id | 필수 | 연동할 서비스의 ID(UUID). 운영 키는 판매 중(ACTIVE) 서비스만, 테스트 키는 삭제되지 않은 본인 서비스를 승인합니다. 기존에 발급된 키는 service_id 생략 시 발급 당시 선택한 서비스를 기준으로 동작합니다. |
state | 권장 | 임의 문자열. 콜백으로 동일한 값이 반환됩니다. |
code_challenge | 선택 | PKCE 챌린지. base64url 43~128자. code_challenge를 전달한 경우 토큰 교환 시 code_verifier가 필수입니다. |
code_challenge_method | 선택 | S256만 지원합니다. plain을 사용하거나 code_challenge를 전달한 상태에서 code_challenge_method를 생략한 경우 invalid_request 오류 화면이 표시됩니다. |
결과(리다이렉트)
| 상황 | 이동 주소 |
|---|---|
| 승인 | {redirect_uri}?code=nxac_…&state={state} |
| 거절 | {redirect_uri}?error=access_denied&state={state} |
| 요청 자체가 잘못됨 | 리다이렉트는 진행되지 않으며 AI Market 오류 화면에 아래 코드가 표시됩니다. 등록되지 않은 주소로는 이동하지 않습니다. |
오류 화면 코드(리다이렉트 없이 화면에 표시)
| 코드 | 원인 |
|---|---|
invalid_client | client_id를 확인할 수 없거나 키가 비활성 상태 |
invalid_redirect | redirect_uri가 등록되지 않았거나 등록된 값과 정확히 일치하지 않음 |
invalid_service | service_id 누락·형식 오류, 본인 서비스가 아니거나 삭제된 경우, 또는 운영 키에서 서비스가 판매 중이 아닌 경우 |
test_owner_only | 테스트 키 연동을 크리에이터 본인 계정이 아닌 다른 계정에서 승인하려는 경우 |
service_unavailable | 서비스 정보를 일시적으로 확인할 수 없는 경우. 잠시 후 다시 요청 |
invalid_request | PKCE 형식 오류(S256이 아니거나 길이 또는 문자 범위를 위반한 경우) |
토큰 발급과 갱신
/api/v1/connect/token서버에서 요청을 전송합니다. Content-Type은 application/x-www-form-urlencoded입니다.grant_type 값에 따라 두 가지 요청을 처리합니다.
grant_type=authorization_code: 인가 코드 교환
| 필드 | 필수 | 설명 |
|---|---|---|
grant_type | 필수 | authorization_code |
code | 필수 | 콜백으로 전달된 인가 코드(10분 유효, 1회 사용) |
client_id | 필수 | 승인 요청에 사용한 키의 클라이언트 ID |
client_secret | 필수 | 클라이언트 시크릿 |
redirect_uri | 필수 | 승인 요청에 전달한 값과 동일 |
code_verifier | 조건부 | 승인 요청에 code_challenge를 전달한 경우 필수. code_challenge 생성에 사용한 원본 값 |
grant_type=refresh_token: 토큰 갱신
| 필드 | 필수 | 설명 |
|---|---|---|
grant_type | 필수 | refresh_token |
refresh_token | 필수 | 보관 중인 갱신 토큰. 토큰 갱신 성공 시 기존 접근 토큰과 갱신 토큰은 즉시 무효화됩니다. |
client_id, client_secret | 필수 | 기존 토큰 발급에 사용한 키 |
응답 200
{ "access_token": "nxa_…", "token_type": "Bearer", "expires_in": 2592000, "refresh_token": "nxr_…" }
| 필드 | 타입 | 설명 |
|---|---|---|
access_token | string | 구독 및 사용량 API에 사용하는 Bearer 토큰(30일). 승인한 사용자와 서비스 조합에만 유효합니다. |
token_type | string | 항상 Bearer |
expires_in | number | 접근 토큰의 유효 기간(초). 2592000 |
refresh_token | string | 갱신 토큰(180일) |
오류
| HTTP | error | 원인 |
|---|---|---|
| 400 | invalid_request | grant_type 누락 또는 지원하지 않는 값 |
| 400 | invalid_grant | 인가 코드 만료·재사용, 다른 키에서 발급된 코드, redirect_uri 불일치, PKCE 검증 실패, 갱신 토큰 만료·갱신·폐기 |
| 401 | invalid_client | client_id와 client_secret 불일치 또는 키 비활성. 보안상 세부 원인은 제공하지 않습니다. |
| 429 | - | 요청 한도 초과(분당 30회) |
토큰 폐기
/api/v1/connect/revoke| 필드 | 필수 | 설명 |
|---|---|---|
token | 필수 | 접근 토큰 또는 갱신 토큰 값. 어느 토큰을 전달해도 연결된 접근 토큰과 갱신 토큰이 모두 폐기됩니다. |
client_id, client_secret | 필수 | 폐기할 토큰 발급에 사용한 키 |
응답은 200 {"ok": true}입니다. 알 수 없는 토큰이나 다른 키에서 발급된 토큰도 200으로 응답하며, 토큰의 존재 여부는 노출하지 않습니다.
클라이언트 인증에 실패한 경우에만 401 invalid_client로 응답합니다.
구독 확인
/api/v1/connect/subscriptionAuthorization: Bearer {access_token} 헤더를 사용하며, 별도 파라미터는 없습니다.
토큰에는 사용자와 서비스가 연결되어 있으며, 구독 상태는 요청 시점에 실시간으로 확인합니다.
| 필드 | 타입 | 설명 |
|---|---|---|
active | boolean | 현재 이용 가능한 구독 여부. status가 ACTIVE, PAST_DUE, CANCEL_SCHEDULED인 경우 true |
status | string | ACTIVE · PAST_DUE · CANCEL_SCHEDULED · EXPIRED · NONE(아래 표) |
mode | string | live · test |
user | object | id(UUID) · email · name · nickname. 연동을 승인한 사용자 |
service | object | id(UUID) · title. 토큰에 연결된 서비스 |
subscription | object | null | 현재 구독 정보. EXPIRED인 경우 마지막 구독 정보를 반환합니다. NONE인 경우 null |
usage | object | null | 월 제공량이 있는 서비스의 유효한 구독인 경우 잔액 요약 usage 객체를 반환합니다. 그 외에는 null |
checkedAt | string | 구독 상태 확인 시각 |
| status | active | 의미 |
|---|---|---|
ACTIVE | true | 정상 구독 상태. nextBillingAt은 다음 결제일 |
PAST_DUE | true | 결제 실패 후 유예 기간(graceUntil)까지 결제를 재시도하며, 해당 기간에는 서비스 이용이 가능합니다. |
CANCEL_SCHEDULED | true | 해지 예정 상태. nextBillingAt은 이용 종료일 |
EXPIRED | false | 이전 구독 이력이 있으나 현재는 만료된 상태. subscription에는 마지막 구독 정보가 반환됩니다. |
NONE | false | 구독 이력이 없는 상태. 단건 판매 서비스의 status는 항상 NONE |
오류: 401 invalid_token(토큰 누락·만료·폐기), 429.
사용량 조회
/api/v1/connect/usageAuthorization: Bearer {access_token} 헤더를 사용합니다.
월 제공량(토큰·크레딧)이 설정된 구독형 서비스에서 유효한 구독이 있는 경우에만 성공합니다.
| 필드 | 타입 | 설명 |
|---|---|---|
active, status, mode | 구독 확인과 동일 | |
user | object | 사용자 id만 반환 |
service | object | 서비스 id만 반환 |
subscription | object | id · planId · planName · nextBillingAt |
usage | object | 사용량 및 잔액 정보 usage 객체 |
checkedAt | string | 사용량 조회 시각 |
오류: 400 usage_not_enabled(월 제공량이 설정되지 않은 서비스), 403 subscription_inactive(유효한 구독이 없는 경우. error_description에 현재 status가 포함됩니다.), 401 invalid_token(토큰 누락·만료·폐기), 429.
사용량 보고
/api/v1/connect/usageAuthorization: Bearer {access_token} 헤더를 사용합니다.
요청 본문은 JSON 또는 폼 인코딩 형식을 지원합니다.
| 필드 | 필수 | 설명 |
|---|---|---|
amount | 필수 | 이번 요청에서 사용한 양(증분). 1 이상 1,000,000,000 이하의 정수 |
idempotencyKey | 권장 | 100자 이하. 동일한 키를 사용한 재요청은 추가 차감 없이 현재 잔액을 반환합니다(report.duplicate: true) |
memo | 선택 | 200자 이하. 서비스 참고용 메모이며, 잔액 계산에는 영향을 주지 않습니다. |
응답 형식은 사용량 조회와 동일하며, report 객체가 추가됩니다.
report 필드 | 타입 | 설명 |
|---|---|---|
amount | number | 이번 요청에서 보고한 사용량 |
fromAllowance | number | 월 제공량에서 차감된 사용량 |
fromTopup | number | 추가 구매분에서 차감된 사용량. 테스트 키는 항상 0 |
overage | number | 잔액 부족으로 차감되지 않은 사용량. 잔액은 0으로 유지되며, 차단 정책은 서비스에서 결정합니다. |
duplicate | boolean | 동일한 idempotencyKey의 중복 요청 여부 |
recordedAt | string | 사용량 기록 시각. 중복 요청인 경우 최초 기록 시각 |
사용량은 월 제공량 → 추가 구매분 순서로 차감됩니다. 오류: 400 invalid_request(amount 누락·0 이하·정수가 아닌 값·상한 초과, idempotencyKey 또는 memo 길이 초과), 400 usage_not_enabled(월 제공량이 설정되지 않은 서비스), 403 subscription_inactive(유효한 구독이 없는 경우. error_description에 현재 status가 포함됩니다.), 401 invalid_token(토큰 누락·만료·폐기), 429.
객체 사전
subscription 객체(구독 확인)
| 필드 | 타입 | 설명 |
|---|---|---|
id | string | 구독 ID |
planId, planName | string | 구독 중인 플랜 정보(구독 시점 기준) |
priceKrw | number | 구독 시점에 확정된 월 결제 금액 |
startedAt | string | 구독 시작 시각 |
nextBillingAt | string | ACTIVE는 다음 결제일, CANCEL_SCHEDULED는 이용 종료일, EXPIRED는 구독 종료 시각 |
cancelledAt | string | null | 해지 신청 시각 |
graceUntil | string | null | PAST_DUE의 유예 종료 시각 |
usage 객체(잔액 요약)
| 필드 | 타입 | 설명 |
|---|---|---|
unit | string | 사용량 단위(예: 토큰, 크레딧). 크리에이터가 설정한 값 |
monthlyTokens | number | 구독 시점에 확정된 월 제공량 |
period | object | start · end · used. 현재 결제 기간 및 기간 내 사용량 |
totalTokens | number | 전체 보유량. 현재 결제 기간의 월 제공량, 이월된 추가 구매분, 기간 중 추가 구매분의 합계 |
totalUsed | number | 전체 사용량. 구독 기간 동안 누적 보고된 사용량 |
remaining | number | 남은 보유량 = allowanceRemaining + topupRemaining |
allowanceRemaining | number | 월 제공량 잔액. 결제일마다 monthlyTokens로 초기화되며 이월되지 않습니다. |
topupRemaining | number | 추가 구매분 잔액. 이월되며, 테스트 키는 항상 0 |
lastReportedAt | string | null | 마지막 사용량 보고 시각 |
오류 형식과 코드
토큰, 구독, 사용량 API의 오류 응답에는 error와 error_description 두 필드가 포함됩니다.
승인 화면의 오류는 화면에 코드로 표시됩니다(승인 화면).
{ "error": "invalid_grant", "error_description": "code expired or already used" }
| HTTP | error | 발생 위치 | 주요 원인 |
|---|---|---|---|
| 400 | invalid_request | token · usage | grant_type 누락 또는 지원하지 않는 값, amount 형식 오류 |
| 400 | invalid_grant | token | 인가 코드 만료·재사용, redirect_uri 불일치, PKCE 검증 실패, 갱신 토큰 만료 또는 이미 갱신된 경우 |
| 401 | invalid_client | token · revoke | client_id와 client_secret 불일치 또는 키 비활성(보안상 세부 원인은 제공하지 않음) |
| 401 | invalid_token | subscription · usage | 접근 토큰 만료·폐기 또는 유효하지 않은 토큰, 키 비활성, 사용자 계정 정지 또는 탈퇴 |
| 400 | usage_not_enabled | usage | 월 제공량이 설정되지 않은 서비스 |
| 403 | subscription_inactive | usage | 유효한 구독이 없는 경우. error_description에 현재 status가 포함됩니다. |
| 503 | temporarily_unavailable | subscription · usage(테스트 키) | 테스트 잔액 생성에 필요한 서비스 정보를 일시적으로 확인할 수 없는 경우. 잠시 후 다시 요청 |
| 429 | - | 전체 | 요청 한도 초과 |
401 응답에는 WWW-Authenticate 헤더가 포함됩니다.invalid_client는 보안상 세부 인증 실패 원인을 구분하지 않습니다.
테스트 키 응답 규칙
테스트 키(nxc_test_…)로 발급한 토큰은 실제 구독과 결제 대신 샌드박스 데이터로 응답합니다.
요청 형식은 운영 키와 동일하며, 다음 항목만 다릅니다.
| 항목 | 운영 키 | 테스트 키 |
|---|---|---|
| 승인할 수 있는 계정 | 모든 사용자 | 키를 발급한 크리에이터 본인 계정만(test_owner_only) |
| 승인할 수 있는 서비스 | 판매 중(ACTIVE) | 키를 발급한 크리에이터가 등록한 서비스 중 삭제되지 않은 서비스(임시저장·검토 중 포함) |
| 승인 화면 | 구독 여부 안내 | '테스트 연동' 표식과 실제 구독·결제에 영향을 주지 않는다는 안내 |
mode | live | test |
/subscription | 실시간 확인 | 항상 active: true, status: ACTIVE.서비스의 첫 번째 플랜을 사용하며, nextBillingAt은 승인 시점으로부터 1개월 후입니다. cancelledAt과 graceUntil은 null입니다. |
/usage | 실제 구독 잔액 | 첫 번째 플랜의 월 제공량으로 테스트 잔액을 생성하며, 1개월마다 자동 초기화됩니다.topupRemaining과 report.fromTopup은 항상 0이며, 월 제공량이 없으면 usage_not_enabled로 응답합니다. |
| 초기화 | - | API 키 또는 샌드박스의 [테스트 데이터 초기화]를 실행하면 테스트 구독, 잔액, 사용량 기록이 삭제되며 토큰은 유지됩니다. |
| 토큰 형식 | nxa_… / nxr_… | nxa_test_… / nxr_test_… |
테스트 키로는 실제 구매자를 검증할 수 없습니다.
운영 환경에 배포하기 전에 운영 키로 교체하고, 응답의 mode가 live인지 확인하세요.