커넥트 API 레퍼런스
엔드포인트별 요청 파라미터, 응답 필드, 오류 코드를 정리했습니다.
단계별 설명은 가이드에서, 직접 실행할 수 있는 도구는 샌드박스에서 확인할 수 있습니다.
기본 정보
| 기본 URL | https://ai-market.co.kr. 승인 화면과 API 호출 모두 이 주소를 사용합니다. |
| 호출 주체 | 모든 API는 서비스를 운영하는 크리에이터의 서버에서 호출합니다. 사용자의 브라우저는 승인 화면( /connect/authorize)으로 이동할 때만 사용됩니다. |
| 인가 방식 | 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(테스트 키)입니다.테스트 키 응답에 대한 자세한 내용은 테스트 키 응답 규칙을 참고하세요. |
인증 방식
| 구분 | 자격 증명 | 사용하는 곳 |
|---|---|---|
| API 키 | Authorization: Basic base64(client_id:client_secret) | /me, /unlink, /subscription, /usage, /disconnections. 서버에서만 요청을 전송하며, 대상 사용자는 userId로 지정합니다(/disconnections는 키 단위 조회라 사용자를 지정하지 않습니다). |
| 클라이언트 인증 | client_id + client_secret(폼 필드 또는 Authorization: Basic 헤더) | /token, /revoke. 서버에서만 요청을 전송합니다. |
| 사용자 자격 | Authorization: Bearer {access_token} | /me. 로그인한 사용자를 확인합니다./unlink, /subscription, /usage도 접근 토큰으로 호출할 수 있으며, 이 경우 토큰의 사용자가 대상입니다. |
| 브라우저 세션 | AI Market 사용자 로그인 세션 | /connect/authorize 승인 화면 |
대상 지정 파라미터
/me, /unlink, /subscription, /usage는 대상 사용자와 서비스를 아래 파라미터로 지정합니다.
GET 요청은 쿼리 파라미터로, POST 요청은 본문 필드로 전달합니다(user_id, service_id 표기도 지원).
| 파라미터 | API 키 인증 | 접근 토큰 인증 | 설명 |
|---|---|---|---|
userId | 필수 | 생략 | 대상 사용자의 ID(UUID). 사용자 정보 조회 응답의 id입니다. 이 키에 연결된 사용자만 지정할 수 있습니다.접근 토큰 인증에서 전달한 경우 토큰의 사용자와 일치해야 합니다. |
serviceId | /subscription, /usage에서 필수 | 선택 | 대상 서비스의 ID(UUID). 본인이 등록한 서비스만 지정할 수 있습니다. 접근 토큰 인증에서 생략하면 승인 요청의 service_id로 지정한 서비스를 사용합니다. |
요청 한도와 유효 기간
| 대상 | 값 |
|---|---|
POST /token, POST /revoke | 클라이언트당 분당 30회. 요청 한도 초과 시 429로 응답합니다. |
GET /me | 분당 300회 |
POST /unlink | 분당 30회 |
GET /disconnections | 분당 60회 |
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로 인가 코드가 전달됩니다.
- AI Market 계정이 없는 사용자는 로그인 화면에서 회원가입(이메일, 카카오, 네이버, Google)을 마친 후 승인 화면으로 돌아옵니다.
- 승인 화면에는 서비스 이름(
service_id를 생략한 경우 크리에이터 이름), 제공되는 정보, 돌아갈 주소가 표시됩니다. - 이미 같은 항목에 동의한 사용자는 승인 화면 없이 바로 인가 코드가 전달됩니다. 요청한
scope가 늘어난 경우 승인 화면이 다시 표시됩니다. - 승인 화면에는 지금 로그인한 AI Market 계정이 표시되며, 사용자는 [다른 계정으로 진행]으로 로그아웃 후 다른 계정으로 로그인해 같은 요청을 이어 갈 수 있습니다.
| 쿼리 파라미터 | 필수 | 설명 |
|---|---|---|
client_id | 필수 | 운영 키 또는 테스트 키의 클라이언트 ID |
redirect_uri | 필수 | 등록된 리다이렉트 URI와 정확히 일치하는 값(URL 인코딩) |
service_id | 선택 | 연동할 서비스의 ID(UUID). 운영 키는 판매 중(ACTIVE) 서비스만, 테스트 키는 삭제되지 않은 본인 서비스를 승인합니다. 생략하면 로그인만 연동합니다. |
scope | 선택 | 제공받을 정보. profile(닉네임, 프로필 사진), email(이메일 주소), name(이름)을 공백으로 구분합니다.생략하면 세 항목을 모두 요청하며, 사용자 ID는 항상 제공됩니다. |
state | 권장 | 임의 문자열. 콜백으로 동일한 값이 반환됩니다. |
response_type | 선택 | code만 지원하며 생략할 수 있습니다. |
prompt | 선택 | consent를 전달하면 이미 동의한 사용자에게도 승인 화면을 표시합니다. |
mode | 선택 | 승인 화면의 용도 문구. login(기본, ‘AI Market 계정으로 로그인’) 또는 link(‘AI Market 계정 연결’). 동의 항목, 결과, 연결은 동일합니다. 다른 값은 invalid_request 오류 화면이 표시됩니다. |
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}?code=nxac_…&state={state} |
| 취소 | {redirect_uri}?error=access_denied&error_description=User+denied+access&state={state} |
| 요청 자체가 잘못됨 | 리다이렉트는 진행되지 않으며 AI Market 오류 화면에 아래 코드가 표시됩니다. 등록되지 않은 주소로는 이동하지 않습니다. |
오류 화면 코드(리다이렉트 없이 화면에 표시)
| 코드 | 원인 |
|---|---|
invalid_client | client_id를 확인할 수 없거나 키가 비활성 상태 |
invalid_redirect | redirect_uri가 등록되지 않았거나 등록된 값과 정확히 일치하지 않음 |
invalid_service | service_id 형식 오류, 본인 서비스가 아니거나 삭제된 경우, 또는 운영 키에서 서비스가 판매 중이 아닌 경우 |
invalid_scope | scope에 지원하지 않는 값이 포함된 경우 |
unsupported_response_type | response_type이 code가 아닌 경우 |
test_owner_only | 테스트 키 연동을 크리에이터 본인 계정이 아닌 다른 계정에서 승인하려는 경우 |
service_unavailable | 서비스 정보를 일시적으로 확인할 수 없는 경우. 잠시 후 다시 요청 |
invalid_request | PKCE 형식 오류(S256이 아니거나 길이 또는 문자 범위를 위반한 경우), 또는 mode가 login·link가 아닌 경우 |
토큰 발급과 갱신
/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 | 필수 | 기존 토큰 발급에 사용한 키 |
client_id와 client_secret은 폼 필드 대신 Authorization: Basic base64(client_id:client_secret) 헤더로 전달할 수 있습니다.
응답 200
{ "access_token": "nxa_…", "token_type": "Bearer", "expires_in": 2592000, "refresh_token": "nxr_…", "refresh_token_expires_in": 15552000, "scope": "profile email name" }
| 필드 | 타입 | 설명 |
|---|---|---|
access_token | string | 사용자 정보 조회에 사용하는 Bearer 토큰(30일). 승인한 사용자와 서비스 조합에만 유효합니다. |
token_type | string | 항상 Bearer |
expires_in | number | 접근 토큰의 유효 기간(초). 2592000 |
refresh_token | string | 갱신 토큰(180일) |
refresh_token_expires_in | number | 갱신 토큰의 유효 기간(초). 15552000 |
scope | string | 사용자가 동의한 항목. 공백으로 구분합니다(예: profile email name). |
오류
| 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/meAI Market 로그인으로 연결된 사용자의 정보를 조회합니다.
로그인 직후에는 Authorization: Bearer {access_token} 헤더로 호출하고, 이후에는 API 키와 userId로 호출할 수 있습니다.
| 쿼리 파라미터 | 필수 | 설명 |
|---|---|---|
userId | API 키 인증에서 필수 | 조회할 사용자의 ID. 접근 토큰 인증에서는 생략합니다. |
{ "id": "22270e30-…", "mode": "live", "scope": "profile email name", "email": "user@example.com", "emailVerified": true,
"name": "홍길동", "nickname": "gildong", "profileImageUrl": "https://ai-market.co.kr/nexa/avatars/…", "connectedAt": "2026-10-06T10:12:44+09:00" }
| 필드 | 타입 | 설명 |
|---|---|---|
id | string | 사용자 ID(UUID). AI Market 계정마다 고정된 값이며 변경되지 않습니다. 승인 화면에서는 ‘회원 번호’로 안내됩니다. |
mode | string | live · test |
scope | string | 사용자가 동의한 항목. 공백으로 구분합니다. |
email | string | null | 이메일 주소. email에 동의한 경우 제공됩니다. |
emailVerified | boolean | null | 이메일 인증 여부. email에 동의한 경우 제공됩니다. |
name | string | null | 이름. name에 동의한 경우 제공됩니다. |
nickname | string | null | 닉네임. profile에 동의한 경우 제공되며, 설정하지 않은 사용자는 null |
profileImageUrl | string | null | 프로필 사진 주소. profile에 동의한 경우 제공되며, 설정하지 않은 사용자는 null |
connectedAt | string | 연결 시각. 연결을 끊은 뒤 다시 동의한 경우 다시 동의한 시각 |
오류: 401 invalid_token(접근 토큰 누락·만료·폐기), 401 invalid_client(API 키 불일치 또는 키 비활성), 403 user_not_connected(연결되지 않은 사용자), 400 invalid_request(userId 누락 또는 형식 오류), 429.
연결 끊기
/api/v1/connect/unlink사용자와 서비스의 연결을 끊습니다. 해당 사용자에게 발급된 접근 토큰과 갱신 토큰이 모두 폐기됩니다.
API 키와 userId로 호출하며, 요청 본문은 JSON 또는 폼 인코딩 형식을 지원합니다.
| 필드 | 필수 | 설명 |
|---|---|---|
userId | API 키 인증에서 필수 | 연결을 끊을 사용자의 ID. 접근 토큰 인증에서는 생략합니다. |
응답은 200 {"id": "22270e30-…"}이며, id는 연결을 끊은 사용자의 ID입니다.
연결이 끊긴 사용자에 대한 요청은 403 user_not_connected로 응답합니다. 이미 연결이 끊긴 사용자의 연결 끊기를 다시 요청한 경우에도 동일합니다.
사용자가 다시 로그인하면 승인 화면에서 동의를 다시 받습니다.
오류: 401 invalid_client(API 키 불일치 또는 키 비활성), 403 user_not_connected(연결되지 않은 사용자), 400 invalid_request(userId 누락 또는 형식 오류), 401 invalid_token(접근 토큰으로 호출한 경우. 토큰 누락·만료·폐기), 429.
연결 끊김 조회
/api/v1/connect/disconnections이 키에서 since 이후에 끊긴 연결을 끊긴 시각 순으로 조회합니다. 사용자가 AI Market 마이페이지에서 연결을 끊었거나 탈퇴한 경우를 서비스가 주기적으로 확인하는 용도입니다.
API 키로만 호출할 수 있으며(접근 토큰 불가), 대상 사용자는 지정하지 않습니다.
| 쿼리 파라미터 | 필수 | 설명 |
|---|---|---|
since | 선택 | 이 시각 이후에 끊긴 연결을 조회합니다. ISO 8601 형식(2026-10-06T09:00:00+09:00, URL 인코딩 시 +는 %2B). 오프셋이 없으면 한국 시간으로 해석하며, 생략하면 7일 전입니다. |
limit | 선택 | 한 번에 받을 최대 건수. 기본 100, 최대 500. |
{ "mode": "live", "since": "2026-10-06T09:00:00+09:00",
"items": [ { "userId": "22270e30-…", "disconnectedAt": "2026-10-06T10:12:44.183+09:00", "by": "user" } ],
"hasMore": false, "next": "2026-10-06T10:12:44.183+09:00" }
| 필드 | 타입 | 설명 |
|---|---|---|
items[].userId | string | 연결이 끊긴 사용자 ID |
items[].disconnectedAt | string | 끊긴 시각(밀리초 포함) |
items[].by | string | null | 끊은 주체. user(사용자가 마이페이지에서 끊음), withdrawal(사용자 탈퇴), service(서비스가 연결 끊기 API로 끊음). 2026-10-06 이전에 끊긴 연결은 null |
hasMore | boolean | limit보다 많은 항목이 남아 있는지 |
next | string | 마지막 항목의 끊긴 시각. 다음 조회의 since로 전달하면 이어서 받을 수 있습니다. 항목이 없으면 요청의 since와 같습니다 |
다시 연결된 사용자는 목록에서 제외됩니다. 같은 사용자가 끊었다가 다시 연결하면 그 사이의 끊김은 조회되지 않습니다.
오류: 401 invalid_client(API 키 불일치, 키 비활성, 또는 접근 토큰으로 호출), 400 invalid_request(since·limit 형식 오류), 429.
구독 확인
/api/v1/connect/subscriptionAPI 키와 userId, serviceId로 해당 사용자의 구독 상태를 조회합니다.
구독 상태는 요청 시점에 실시간으로 확인합니다.
| 쿼리 파라미터 | 필수 | 설명 |
|---|---|---|
userId | 필수 | 구독을 확인할 사용자의 ID |
serviceId | 필수 | 구독을 확인할 서비스의 ID. 본인이 등록한 서비스만 지정할 수 있습니다. |
| 필드 | 타입 | 설명 |
|---|---|---|
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. 조회한 사용자. 사용자가 동의하지 않은 항목은 null |
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_client(API 키 불일치 또는 키 비활성), 403 user_not_connected(연결되지 않은 사용자), 403 invalid_service(본인이 등록한 서비스가 아니거나 삭제된 서비스), 400 invalid_request(userId·serviceId 누락 또는 형식 오류), 401 invalid_token(접근 토큰으로 호출한 경우. 토큰 누락·만료·폐기), 429.
사용량 조회
/api/v1/connect/usageAPI 키와 userId, serviceId로 해당 사용자의 사용량과 잔액을 조회합니다.
월 제공량(토큰·크레딧)이 설정된 구독형 서비스에서 유효한 구독이 있는 경우에만 성공합니다.
| 쿼리 파라미터 | 필수 | 설명 |
|---|---|---|
userId | 필수 | 사용량을 조회할 사용자의 ID |
serviceId | 필수 | 사용량을 조회할 서비스의 ID |
| 필드 | 타입 | 설명 |
|---|---|---|
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가 포함됩니다.), 403 user_not_connected(연결되지 않은 사용자), 403 invalid_service(본인이 등록한 서비스가 아니거나 삭제된 서비스), 400 invalid_request(userId·serviceId 누락 또는 형식 오류), 401 invalid_client(API 키 불일치 또는 키 비활성), 401 invalid_token(접근 토큰으로 호출한 경우. 토큰 누락·만료·폐기), 429.
사용량 보고
/api/v1/connect/usageAPI 키로 호출하며, userId로 지정한 사용자의 잔액에서 amount만큼 차감합니다.
요청 본문은 JSON 또는 폼 인코딩 형식을 지원합니다.
| 필드 | 필수 | 설명 |
|---|---|---|
userId | 필수 | 사용량을 차감할 사용자의 ID |
serviceId | 필수 | 사용량이 발생한 서비스의 ID |
amount | 필수 | 이번 요청에서 사용한 양(증분). 1 이상 1,000,000,000 이하의 정수 |
idempotencyKey | 권장 | 100자 이하. 동일한 키를 사용한 재요청은 추가 차감 없이 현재 잔액을 반환합니다(report.duplicate: true) |
memo | 선택 | 200자 이하. 서비스 참고용 메모이며, 잔액 계산에는 영향을 주지 않습니다. |
curl -X POST https://ai-market.co.kr/api/v1/connect/usage \
-u nxc_xxxxx:nxs_xxxxx -H "Content-Type: application/json" \
-d '{"userId": "22270e30-…", "serviceId": "68f5f1e7-…", "amount": 150, "idempotencyKey": "req-20260922-0001"}'
응답 형식은 사용량 조회와 동일하며, report 객체가 추가됩니다.
report 필드 | 타입 | 설명 |
|---|---|---|
amount | number | 이번 요청에서 보고한 사용량 |
fromAllowance | number | 월 제공량에서 차감된 사용량 |
fromTopup | number | 추가 구매분에서 차감된 사용량. 테스트 키는 항상 0 |
overage | number | 잔액 부족으로 차감되지 않은 사용량. 잔액은 0으로 유지되며, 차단 정책은 서비스에서 결정합니다. |
duplicate | boolean | 동일한 idempotencyKey의 중복 요청 여부 |
recordedAt | string | 사용량 기록 시각. 중복 요청인 경우 최초 기록 시각 |
사용량은 월 제공량 → 추가 구매분 순서로 차감됩니다. 오류: 400 invalid_request(userId·serviceId 누락 또는 형식 오류, amount 누락·0 이하·정수가 아닌 값·상한 초과, idempotencyKey 또는 memo 길이 초과), 400 usage_not_enabled(월 제공량이 설정되지 않은 서비스), 403 subscription_inactive(유효한 구독이 없는 경우. error_description에 현재 status가 포함됩니다.), 403 user_not_connected(연결되지 않은 사용자), 403 invalid_service(본인이 등록한 서비스가 아니거나 삭제된 서비스), 401 invalid_client(API 키 불일치 또는 키 비활성), 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 객체(잔액 요약)
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 · me · unlink · subscription · usage | grant_type 누락 또는 지원하지 않는 값, userId·serviceId 누락 또는 형식 오류, amount 형식 오류 |
| 400 | invalid_grant | token | 인가 코드 만료·재사용, redirect_uri 불일치, PKCE 검증 실패, 갱신 토큰 만료 또는 이미 갱신된 경우 |
| 401 | invalid_client | token · revoke · disconnections · API 키로 호출한 모든 API | client_id와 client_secret 불일치 또는 키 비활성(보안상 세부 원인은 제공하지 않음) |
| 401 | invalid_token | 접근 토큰으로 호출한 me · unlink · subscription · usage | 접근 토큰 만료·폐기 또는 유효하지 않은 토큰, 키 비활성, 사용자 계정 정지 또는 탈퇴 |
| 403 | user_not_connected | me · unlink · subscription · usage | userId의 사용자가 연결되어 있지 않은 경우. 승인 이력 없음, 연결 끊기, 계정 정지 또는 탈퇴가 해당되며 보안상 세부 원인은 제공하지 않음 |
| 403 | invalid_service | subscription · usage | serviceId가 본인이 등록한 서비스가 아니거나 삭제된 서비스 |
| 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) |
userId로 지정할 수 있는 사용자 | 연결된 모든 사용자 | 키를 발급한 크리에이터 본인의 사용자 ID만 |
| 승인할 수 있는 서비스 | 판매 중(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인지 확인하세요.